1 Project setup

1.0.1 Packages

Install packages if necessary. Listed are installers for packages not on CRAN and the devlopment (most up-to-date) version of STEPS.

# library(devtools)
# install_github("steps-dev/steps")
# install_github("smwindecker/gdaltools")

Load packages

library(raster)
library(dplyr)
library(tibble)
library(sf)
library(rgdal)
library(readr)
library(readxl)
library(ggplot2)
library(lubridate)
library(magrittr)
library(tidyr)
library(foreach)
library(doMC)
library(future)
library(future.apply)
library(tidyr)
library(dismo)
library(gbm)
library(steps)
library(gdaltools)

1.0.2 Functions

source(file = "R/functions/pg.sf.R")
source(file = "R/functions/pg.pa.R")
source(file = "R/functions/read.vba.R")
source(file = "R/functions/proc.vba.R")
source(file = "R/functions/get.landis.vars.R")
source(file = "R/functions/rascc.R")
source(file = "R/functions/read.multi.line.header.R")
source(file = "R/functions/interpolate.climdat.R")
source(file = "R/functions/get.rst.prop.R")
source(file = "R/functions/get.rst.dat.R")

1.0.3 Paths

proj_path <- "/home/landis/rfst/"
# proj_path <- "D:/Users/ryan/Dropbox/Work/RFA_STEPS/rfst/"

2 Prepare variables

2.1 Analysis parameters

2.1.1 Timesteps

ntimesteps <- 50
ncores <- 20

2.2 Geographic data

2.2.1 Landscape

Set up base landscape layer

ch_rst <- raster(x = "data/grids/eco_v12.img") %T>%
  plot

ch_proj <- ch_rst@crs
ch_extent <- extent(ch_rst)
ch_res <- res(ch_rst)

2.2.2 Boundaries

rfa <- read_sf("data/shapefiles/RFA/")%>%
  st_transform(crs = ch_proj)
rfa
Simple feature collection with 81 features and 7 fields
geometry type:  POLYGON
dimension:      XY
bbox:           xmin: -57985.97 ymin: 5665387 xmax: 763088.7 ymax: 6223446
epsg (SRID):    NA
proj4string:    +proj=utm +zone=55 +south +ellps=GRS80 +towgs84=0,0,0,-0,-0,-0,0 +units=m +no_defs
pg.sf(rfa)

ch_rfa <- rfa[rfa$NAME== "CENTRAL HIGHLANDS",] 
ch_rfa
Simple feature collection with 1 feature and 7 fields
geometry type:  POLYGON
dimension:      XY
bbox:           xmin: 318074.3 ymin: 5770575 xmax: 452175.7 ymax: 5906852
epsg (SRID):    NA
proj4string:    +proj=utm +zone=55 +south +ellps=GRS80 +towgs84=0,0,0,-0,-0,-0,0 +units=m +no_defs
pg.sf(ch_rfa)

ch_mask <- rasterize(ch_rfa, ch_rst, field = 1, filename = "./output/landscape_vars/ch_mask.grd", overwrite = TRUE) 
ch_mask[ch_rst == 132] <- NA # removes lake areas from habitat
plot(ch_mask)

Think carefully about using this layer as projections are for zone 55, so distorts west of the state

victoria <- read_sf("data/shapefiles/vicstatepolygon/") %>%
   st_transform(crs = ch_proj)

2.3 Occurrence data

pseudo_abs <- read_sf("data/shapefiles/pseudo_absences/pseudo_absences.shp")%>%
  st_transform(crs = st_crs(ch_rst)) %>%
  mutate(PA = 0) %>%
  select(PA, geometry) %>%
  st_zm(drop = TRUE)
pseudo_abs
Simple feature collection with 35 features and 1 field
geometry type:  POINT
dimension:      XY
bbox:           xmin: 325312 ymin: 5774360 xmax: 445518.4 ymax: 5901431
epsg (SRID):    NA
proj4string:    +proj=utm +zone=55 +south +ellps=GRS80 +towgs84=0,0,0,-0,-0,-0,0 +units=m +no_defs

2.3.1 GG Occurrence data

Read in data

gg_ari <- read_excel(path = "data/tabular/BoA_SB_Combined_VBA_upload_v4.xls") %>%
  dplyr::select(-starts_with("leave")) %>%
  rename("lon" = `X-coordinate (easting or longitude)`, "lat" = `Y-coordinate (northing or latitude)`) %>%
   fill(lon, lat, .direction = "down") %>%
  filter(`Taxon Name` == "Misc Target taxa not found") %>%
  select(lon, lat) %>%
  mutate(PA = 0) %>%
  st_as_sf(coords = c("lon", "lat"), crs = st_crs(28355)) %>%
  st_transform(crs = st_crs(ch_rst))

-
/
                                                                                                                  
New names:
* `leave blank` -> `leave blank...2`
* `leave blank` -> `leave blank...3`
* `leave blank` -> `leave blank...6`
* `leave blank` -> `leave blank...7`
* `leave blank` -> `leave blank...25`
gg_ari
Simple feature collection with 51 features and 1 field
geometry type:  POINT
dimension:      XY
bbox:           xmin: 333214 ymin: 5779763 xmax: 451285 ymax: 5937215
epsg (SRID):    28355
proj4string:    +proj=utm +zone=55 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs
gg_vba <- proc.vba("data/tabular/vba_gg_all_20190509.csv", project.crs = ch_proj)
gg_vba
Simple feature collection with 3086 features and 1 field
geometry type:  POINT
dimension:      XY
bbox:           xmin: 248825.6 ymin: 5725915 xmax: 742929.5 ymax: 6008846
epsg (SRID):    NA
proj4string:    +proj=utm +zone=55 +south +ellps=GRS80 +towgs84=0,0,0,-0,-0,-0,0 +units=m +no_defs
gg_pa_all <- gg_vba %>%
  rbind(gg_ari)
gg_pa_all
Simple feature collection with 3137 features and 1 field
geometry type:  POINT
dimension:      XY
bbox:           xmin: 248825.6 ymin: 5725915 xmax: 742929.5 ymax: 6008846
epsg (SRID):    NA
proj4string:    +proj=utm +zone=55 +south +ellps=GRS80 +towgs84=0,0,0,-0,-0,-0,0 +units=m +no_defs
plot_gg_pa_all <- pg.pa(gg_pa_all, ch_rfa) +
  geom_sf(data = victoria, fill = NA)
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
plot_gg_pa_all

gg_pa_ch <- gg_pa_all[ch_rfa,]
gg_pa_ch
Simple feature collection with 1308 features and 1 field
geometry type:  POINT
dimension:      XY
bbox:           xmin: 333053.7 ymin: 5783845 xmax: 448916.2 ymax: 5887474
epsg (SRID):    NA
proj4string:    +proj=utm +zone=55 +south +ellps=GRS80 +towgs84=0,0,0,-0,-0,-0,0 +units=m +no_defs
gg_pa_ch_psab <- gg_pa_ch %>%
  rbind(pseudo_abs)
st_write(gg_pa_ch, "output/shapefiles/pa/ch/gg_pa_ch.shp", delete_layer = TRUE)
Deleting layer `gg_pa_ch' using driver `ESRI Shapefile'
Writing layer `gg_pa_ch' to data source `output/shapefiles/pa/ch/gg_pa_ch.shp' using driver `ESRI Shapefile'
features:       1308
fields:         1
geometry type:  Point
st_write(gg_pa_ch_psab, "output/shapefiles/pa/ch/gg_pa_ch_psab.shp", delete_layer = TRUE)
Deleting layer `gg_pa_ch_psab' using driver `ESRI Shapefile'
Writing layer `gg_pa_ch_psab' to data source `output/shapefiles/pa/ch/gg_pa_ch_psab.shp' using driver `ESRI Shapefile'
features:       1343
fields:         1
geometry type:  Point
pg_gg_pa_ch <- pg.pa(gg_pa_ch %>% mutate(pseudo_abs = "vba") %>% rbind(pseudo_abs %>% mutate(pseudo_abs = "pseudo_absences")), ch_rfa) +
  facet_grid(.~pseudo_abs)
pg_gg_pa_ch

2.3.2 LBP Occurrence data

lb_pa_all <- proc.vba("data/tabular/vba_lb_all_20190509.csv", project.crs = ch_proj)
plot_lb_pa_all <- pg.pa(lb_pa_all, ch_rfa) +
  geom_sf(data = victoria, fill = NA)
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
plot_lb_pa_all

lb_pa_ch <- lb_pa_all[ch_rfa,]
lb_pa_ch
Simple feature collection with 1404 features and 1 field
geometry type:  POINT
dimension:      XY
bbox:           xmin: 364618.3 ymin: 5798912 xmax: 447312.4 ymax: 5868055
epsg (SRID):    NA
proj4string:    +proj=utm +zone=55 +south +ellps=GRS80 +towgs84=0,0,0,-0,-0,-0,0 +units=m +no_defs
lb_pa_ch_psab <- lb_pa_ch %>%
  rbind(pseudo_abs)
st_write(lb_pa_ch, "output/shapefiles/pa/ch/lb_pa_ch.shp", delete_layer = TRUE)
Deleting layer `lb_pa_ch' using driver `ESRI Shapefile'
Writing layer `lb_pa_ch' to data source `output/shapefiles/pa/ch/lb_pa_ch.shp' using driver `ESRI Shapefile'
features:       1404
fields:         1
geometry type:  Point
st_write(lb_pa_ch_psab, "output/shapefiles/pa/ch/lb_pa_ch_psab.shp", delete_layer = TRUE)
Deleting layer `lb_pa_ch_psab' using driver `ESRI Shapefile'
Writing layer `lb_pa_ch_psab' to data source `output/shapefiles/pa/ch/lb_pa_ch_psab.shp' using driver `ESRI Shapefile'
features:       1439
fields:         1
geometry type:  Point
pg_lb_pa_ch <- pg.pa(lb_pa_ch %>% mutate(pseudo_abs = "vba") %>% rbind(pseudo_abs %>% mutate(pseudo_abs = "pseudo_absences")), ch_rfa) +
  facet_grid(.~pseudo_abs)
pg_lb_pa_ch

save.image("output/session_images/landscape-occupancy.RData")
#load(file = "output/session_images/landscape-occupancy.RData")

2.4 Landis output

2.4.1 Scenario 1: Current planned burning, current timber harvesting, climate change under RCP 4.5, current bushfire regime (Buisness as usual)

aa <- get.landis.vars(
  scn_path = "~/landis_ch_s1_pb-th-cc_50/",
  proj_path = proj_path,
  out_path = "/output/habitat_vars/",
  scn_id = "s1",
  proj_mask = ch_mask,
  timesteps = 3,
  cores = 4
  )

plot(s1_vars_landis[[ntimesteps + 1]])

save(s1_vars_landis, file = "output/habitat_vars/s1_vars_landis")

# load(file = "output/habitat_vars/s1_vars_landis_fut")

2.4.2 Scenario 2: Current planned burning, current timber harvesting, climate change under RCP 8.5, increatred bushfire regime

2.4.3 Scenario 3: Current planned burning, current timber harvesting, no climate change, current bushfire regime

s3_vars_landis <- get.landis.vars(
  scn_path = "~/landis_ch_s3_pb-th-cc0_50/",
  proj_path = proj_path,
  out_path = "/output/habitat_vars/",
  scn_id = "s3",
  proj_mask = ch_mask,
  timesteps = ntimesteps,
  cores = ncores
  )
plot(s3_vars_landis[[1]])

plot(s3_vars_landis[[ntimesteps + 1]])

save(s3_vars_landis, file = "output/habitat_vars/s3_vars_landis")
# load(file = "output/habitat_vars/s3_vars_landis_fut")

2.4.4 Scenario 4: Current planned burning, no harvesting, climate change under RCP 4.5, current bushfire regime

s4_vars_landis <- get.landis.vars(
  scn_path = "~/landis_ch_s4_pb-th0-cc_50/",
  proj_path = proj_path,
  out_path = "/output/habitat_vars/",
  scn_id = "s4",
  proj_mask = ch_mask,
  timesteps = ntimesteps,
  cores = ncores,
  harvest_timber = FALSE
  )
plot(s4_vars_landis[[1]])

plot(s4_vars_landis[[ntimesteps + 1]])

save(s4_vars_landis, file = "output/habitat_vars/s4_vars_landis")
# load(file = "output/habitat_vars/s4_vars_landis_fut")

2.5 ARI Data

2.5.1 Anisotronic heating x ruggedness

ahr <-raster(x = "data/grids/Env_covariates_noClimate_VicGrid94/Anisotrophic_Heating_Ruggedness") %>%
  projectRaster(to = ch_mask) %>%
  mask(mask = ch_mask, filename = "output/habitat_vars/ari_ahr.grd") %T>%
  plot
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf

2.5.2 Log verticical distance all wetlands

lvdaw <- raster(x = "data/grids/Env_covariates_noClimate_VicGrid94/log_vertical_distance_all_wetlands_sept2012") %>%
  projectRaster(to = ch_mask) %>%
  mask(mask = ch_mask, filename = "output/habitat_vars/ari_lvdaw.grd") %T>%
  plot
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf

2.5.3 Log vertical distance major streams

lvdma <- raster(x = "data/grids/Env_covariates_noClimate_VicGrid94/log_vertical_distance_major_streams_sept2012") %>%
  projectRaster(to = ch_mask) %>%
  mask(mask = ch_mask, filename = "output/habitat_vars/ari_lvdma.grd") %T>%
  plot
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf

2.5.4 Log vertical distance minor streams

lvdmi <- raster(x = "data/grids/Env_covariates_noClimate_VicGrid94/log_vertical_distance_minor_streams_sept2012") %>%
  projectRaster(to = ch_mask) %>%
  mask(mask = ch_mask) %T>%
  plot
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf

2.5.5 Log vertical distance saline wetlands

lvdsw <- raster(x = "data/grids/Env_covariates_noClimate_VicGrid94/log_vertical_distance_saline_wetlands_sept2012") %>%
  projectRaster(to = ch_mask) %>%
  mask(mask = ch_mask, filename = "output/habitat_vars/ari_lvdsw.grd") %T>%
  plot
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf

2.5.6 Relative annual insolation

rai <- raster(x = "data/grids/Env_covariates_noClimate_VicGrid94/relative_annual_insolation_sept2012") %>%
  projectRaster(to = ch_mask) %>%
  mask(mask = ch_mask, filename = "output/habitat_vars/ari_rai.grd") %T>%
  plot
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf

2.5.7 Thorium

tho <- raster(x = "data/grids/Env_covariates_noClimate_VicGrid94/sept2014thorium") %>%
  projectRaster(to = ch_mask) %>%
  mask(mask = ch_mask, filename = "output/habitat_vars/ari_tho.grd") %T>%
  plot
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf

2.5.8 Visible sky index

vsky <- raster(x = "data/grids/Env_covariates_noClimate_VicGrid94/visible_sky_sept2012") %>%
  projectRaster(to = ch_mask) %>%
  mask(mask = ch_mask, filename = "output/habitat_vars/ari_vsky.grd") %T>%
  plot
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf

2.5.9 Topographic wetness index

twi <- raster(x = "data/grids/Env_covariates_noClimate_VicGrid94/wetness_index_topocrop_sept2012") %>%
  projectRaster(to = ch_mask) %>%
  mask(mask = ch_mask, filename = "output/habitat_vars/ari_twi.grd") %T>%
  plot
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf

2.5.10 Wind exposition

Problem with layer

# winex <- raster(x = "data/grids/Env_covariates_noClimate_VicGrid94/wind_exposition2015") %>%
  # projectRaster(to = ch_mask) %>%
  # mask(mask = ch_mask, filename = "output/habitat_vars/ari_winex.grd") %T>%
  # plot

2.5.11 ARI variables stack

2.5.11.1 Initial variables

ari_iv <- stack(lvdaw, lvdma, lvdmi, lvdsw)
names(ari_iv) <- c("lvdaw", "lvdma", "lvdmi", "lvdsw")

2.5.11.2 Future variables

Repeates into list for each year

ari_v <- vector("list", ntimesteps + 1)
for(i in 1:(ntimesteps+1)){
  ari_v[[i]] <- ari_iv
}

2.6 Climactic data

pc ~ percentage change ac ~ absolute change

tmax ~ max temperature tmin ~ minimum temperature prec ~ precipitation evtr ~ evapotranspiration

01 ~ January 07 ~ July

4.5 ~ rcp 4.5 8.5 ~ rcp 8.5

2.6.1 Current climate

From WorldClim

2.6.1.1 Precipitation in January

prec01 <- raster("data/grids/wc2.0_30s_prec_01.tif") %>%
  projectRaster(to = ch_mask) %>%
  mask(mask = ch_mask, filename = "output/clim_vars/prec01.grd")
3 projected point(s) not finiteno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
names(prec01) <- "prec01"
plot(prec01)

2.6.1.2 Precipitation in July

prec07 <- raster("data/grids/wc2.0_30s_prec_07.tif") %>%
  projectRaster(to = ch_mask) %>%
  mask(mask = ch_mask, filename = "output/clim_vars/prec07.grd")
3 projected point(s) not finiteno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
names(prec07) <- "prec07"
plot(prec07)

2.6.1.3 Max temperature in January

tmax01 <- raster("data/grids/wc2.0_30s_tmax_01.tif") %>%
  projectRaster(to = ch_mask) %>%
  mask(mask = ch_mask, filename = "output/clim_vars/tmax01.grd")
3 projected point(s) not finiteno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
names(tmax01) <- "tmax01"
plot(tmax01)

2.6.1.4 Minimum temperature in July

tmin07 <- raster("data/grids/wc2.0_30s_tmin_07.tif") %>%
  projectRaster(to = ch_mask) %>%
  mask(mask = ch_mask, filename = "output/clim_vars/tmin07.grd")
3 projected point(s) not finiteno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
names(tmin07) <- "tmin07"
plot(tmin07)

2.6.2 Future climate

Data from Climate Change in Australia

2.6.2.1 Change data

There should be new data to replace this ##### Absolute change in temperature Get raw data

#absolute change in temp
raw_tmax01_4.5_ac <- read.multi.line.header(file = "http://nrm-erddap.nci.org.au/erddap/griddap/tasmax_Amon_CSIRO-Mk3-6-0_rcp45_r1i1p1_abs-change-wrt-seasavg-clim_native.csv?tasmax_january[(2025-01-01T12:00:00Z):1:(2090-01-01T12:00:00Z)][(-40.10297775):1:(-32.64199448)][(140.625):1:(150)]")
Read 4 items
raw_tmax01_8.5_ac <- read.multi.line.header(file = "http://nrm-erddap.nci.org.au/erddap/griddap/tasmax_Amon_CSIRO-Mk3-6-0_rcp85_r1i1p1_abs-change-wrt-seasavg-clim_native.csv?tasmax_january[(2025-01-01T12:00:00Z):1:(2090-01-01T12:00:00Z)][(-40.10297775):1:(-32.64199448)][(140.625):1:(150)]")
Read 4 items
raw_tmin07_4.5_ac <- read.multi.line.header(file = "http://nrm-erddap.nci.org.au/erddap/griddap/tasmin_Amon_CSIRO-Mk3-6-0_rcp45_r1i1p1_abs-change-wrt-seasavg-clim_native.csv?tasmin_july[(2025-01-01T12:00:00Z):1:(2090-01-01T12:00:00Z)][(-40.10297775):1:(-32.64199448)][(140.625):1:(150)]") 
Read 4 items
raw_tmin07_8.5_ac <- read.multi.line.header(file = "http://nrm-erddap.nci.org.au/erddap/griddap/tasmin_Amon_CSIRO-Mk3-6-0_rcp85_r1i1p1_abs-change-wrt-seasavg-clim_native.csv?tasmin_july[(2025-01-01T12:00:00Z):1:(2090-01-01T12:00:00Z)][(-40.10297775):1:(-32.64199448)][(140.625):1:(150)]")
Read 4 items

Years data available

n_tmax01_4.5 <- as.numeric(sub("-.*", "", unique(raw_tmax01_4.5_ac$time)))
n_tmax01_8.5 <- as.numeric(sub("-.*", "", unique(raw_tmax01_8.5_ac$time)))
n_tmin07_4.5 <- as.numeric(sub("-.*", "", unique(raw_tmin07_4.5_ac$time)))
n_tmin07_8.5 <- as.numeric(sub("-.*", "", unique(raw_tmin07_8.5_ac$time)))

Reprojected layers

tmax01_4.5_ac <- rascc(raw_tmax01_4.5_ac, new.proj.layer = ch_mask, filename = "output/clim_vars/tmax01_4.5_ac.grd")
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
tmax01_8.5_ac <- rascc(raw_tmax01_8.5_ac, new.proj.layer = ch_mask, filename = "output/clim_vars/tmax01_8.5_ac.grd")
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
tmin07_4.5_ac <- rascc(raw_tmin07_4.5_ac, new.proj.layer = ch_mask, filename = "output/clim_vars/tmin07_4.5_ac.grd")
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
tmin07_8.5_ac <- rascc(raw_tmin07_8.5_ac, new.proj.layer = ch_mask, filename = "output/clim_vars/tmin07_8.5_ac.grd")
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
2.6.2.1.1 Percentage change in precipitation

Get raw data

raw_prec01_4.5_pc <- read.multi.line.header(file = "http://nrm-erddap.nci.org.au/erddap/griddap/pr_Amon_CSIRO-Mk3-6-0_rcp45_r1i1p1_perc-change-wrt-seassum-clim_native.csv?pr_january[(2025-01-01T12:00:00Z):1:(2090-01-01T12:00:00Z)][(-40.10297775):1:(-32.64199448)][(140.625):1:(150)]")
Read 4 items
raw_prec01_8.5_pc <- read.multi.line.header(file = "http://nrm-erddap.nci.org.au/erddap/griddap/pr_Amon_CSIRO-Mk3-6-0_rcp85_r1i1p1_perc-change-wrt-seassum-clim_native.csv?pr_january[(2025-01-01T12:00:00Z):1:(2090-01-01T12:00:00Z)][(-40.10297775):1:(-32.64199448)][(140.625):1:(150)]")
Read 4 items
raw_prec07_4.5_pc <- read.multi.line.header(file = "http://nrm-erddap.nci.org.au/erddap/griddap/pr_Amon_CSIRO-Mk3-6-0_rcp45_r1i1p1_perc-change-wrt-seassum-clim_native.csv?pr_july[(2025-01-01T12:00:00Z):1:(2090-01-01T12:00:00Z)][(-40.10297775):1:(-32.64199448)][(140.625):1:(150)]")
Read 4 items
raw_prec07_8.5_pc <- read.multi.line.header(file = "http://nrm-erddap.nci.org.au/erddap/griddap/pr_Amon_CSIRO-Mk3-6-0_rcp85_r1i1p1_perc-change-wrt-seassum-clim_native.csv?pr_july[(2025-01-01T12:00:00Z):1:(2090-01-01T12:00:00Z)][(-40.10297775):1:(-32.64199448)][(140.625):1:(150)]")
Read 4 items

Years data available

n_prec01_4.5 <- as.numeric(sub("-.*", "", unique(raw_prec01_4.5_pc$time)))
n_prec01_8.5 <- as.numeric(sub("-.*", "", unique(raw_prec01_4.5_pc$time)))
n_prec07_4.5 <- as.numeric(sub("-.*", "", unique(raw_prec07_4.5_pc$time)))
n_prec07_8.5 <- as.numeric(sub("-.*", "", unique(raw_prec07_4.5_pc$time)))

Reprojected layers

prec01_4.5_pc <- rascc(raw_prec01_4.5_pc, new.proj.layer = ch_mask, filename = "output/clim_vars/prec01_4.5_pc.grd")
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
prec01_8.5_pc <- rascc(raw_prec01_8.5_pc, new.proj.layer = ch_mask, filename = "output/clim_vars/prec01_8.5_pc.grd")
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
prec07_4.5_pc <- rascc(raw_prec07_4.5_pc, new.proj.layer = ch_mask, filename = "output/clim_vars/prec07_4.5_pc.grd")
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
prec07_8.5_pc <- rascc(raw_prec07_8.5_pc, new.proj.layer = ch_mask, filename = "output/clim_vars/prec07_8.5_pc.grd")
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf

2.6.2.2 Absolute predicted values

2.6.2.2.1 Temperature

add new function that writes these climate layers to files.

2.6.2.2.1.1 Jan max temperature RCP 4.5
tmax01_4.5 <- rst.op(input1 = tmax01,
                     input2 = tmax01_4.5_ac,
                     proj_mask = ch_mask,
                     op = "addabs",
                     filename = "output/clim_vars/tmax01_4.5",
                     layernames = n_tmax01_4.5) %T>%
  plot

2.6.2.2.1.2 Jan max temperature RCP 8.5
tmax01_8.5 <- rst.op(input1 = tmax01,
                     input2 = tmax01_8.5_ac,
                     proj_mask = ch_mask,
                     op = "addabs",
                     filename = "output/clim_vars/tmax01_8.5",
                     layernames = n_tmax01_8.5) %T>%
  plot

2.6.2.2.1.3 July min temperature RCP 4.5
tmin07_4.5 <- rst.op(input1 = tmin07,
                     input2 = tmin07_4.5_ac,
                     proj_mask = ch_mask,
                     op = "addabs",
                     filename = "output/clim_vars/tmin07_4.5",
                     layernames = n_tmin07_4.5) %T>%
  plot
2.6.2.2.1.4 July min temperature RCP 8.5
tmin07_8.5 <- rst.op(input1 = tmin07,
                     input2 = tmin07_8.5_ac,
                     proj_mask = ch_mask,
                     op = "addabs",
                     filename = "output/clim_vars/tmin07_8.5",
                     layernames = n_tmin07_8.5) %T>%
  plot
2.6.2.2.2 Precipitation
2.6.2.2.3 January precipitation RCP 4.5
prec01_4.5 <- rst.op(input1 = prec01,
                     input2 = prec01_4.5_pc,
                     proj_mask = ch_mask,
                     op = "addper",
                     filename = "output/clim_vars/prec01_4.5",
                     layernames = n_prec01_4.5) %T>%
  plot

2.6.2.2.4 January precipitation RCP 8.5
prec01_8.5 <- rst.op(input1 = prec01,
                     input2 = prec01_8.5_pc,
                     proj_mask = ch_mask,
                     op = "addper",
                     filename = "output/clim_vars/prec01_8.5",
                     layernames = n_prec01_8.5) %T>%
  plot
2.6.2.2.5 July precipitation RCP 4.5
prec07_4.5 <- rst.op(input1 = prec07,
                     input2 = prec07_4.5_pc,
                     proj_mask = ch_mask,
                     op = "addper",
                     filename = "output/clim_vars/prec07_4.5",
                     layernames = n_prec07_4.5) %T>%
  plot
2.6.2.2.6 July precipitation RCP 8.5
prec07_8.5 <- rst.op(input1 = prec07,
                     input2 = prec07_8.5_pc,
                     proj_mask = ch_mask,
                     op = "addper",
                     filename = "output/clim_vars/prec07_8.5",
                     layernames = n_prec07_8.5) %T>%
  plot

2.6.2.3 Interploate prediction data

Currently just repeats predictions for nearest year, need updating to weight predictions within 10 years, cf data from CSIRO

2.6.3 Climate variable sets

2.6.3.1 Initial climate variables

clim_iv <- stack(prec01, prec07, tmax01, tmin07)

2.6.3.2 Future climate variables

clim_fv_cc0 <- vector("list", 50)
for(i in 1:50){
  clim_fv_cc0[[i]] <- clim_iv
}


clim_fv_4.5 <- mapply(prec01_4.5_int, prec07_4.5_int, tmax01_4.5_int, tmin07_4.5_int, FUN = stack)
clim_fv_8.5 <- mapply(prec01_8.5_int, prec07_8.5_int, tmax01_8.5_int, tmin07_8.5_int, FUN = stack)
save.image(file = "output/input_variables.RData")

2.7 Distribution model variables

2.7.1 Species LANDIS variables

2.7.1.1 GG LANDIS vars

gglv <- c("ggf", "ggd", "hbt_1k")

2.7.1.2 LB LANDIS vars

lblv <- c("lbm", "hbt_3h")

2.7.2 Scenario 1

2.7.2.1 Greater Glider

2.7.2.1.1 Scenario 1 initial variables
s1_iv_gg <- stack(s1_vars_landis_init[[c(gglv)]], clim_iv)

save(s1_iv_gg, file = "output/habitat_vars/s1_iv_gg")
2.7.2.1.2 Scenaio 1 model data
s1_md_gg <- s1_iv_gg %>%
  raster::extract(y = st_coordinates(gg_pa_ch)) %>%
  cbind("PA" = gg_pa_ch$PA, .) %>%
  as.data.frame %>%
  na.omit 

s1_md_gg

save(s1_md_gg, file = "output/habitat_vars/s1_md_gg")
2.7.2.1.3 Scenario 1 future variables
s1_fv_gg <- s1_vars_landis_fut %>%
  sapply("[[", gglv) %>%
  mapply(clim_fv_4.5, FUN = stack)

save(s1_fv_gg, file = "output/habitat_vars/s1_fv_gg")

2.7.2.2 Leadbeater’s Possum

2.7.2.2.1 Scenario 1 initial variables
s1_iv_lb <- stack(s1_vars_landis_init[[c(lblv)]], clim_iv)

save(s1_iv_lb, file = "output/habitat_vars/s1_iv_lb")
2.7.2.2.2 Scenaio 1 model data
s1_md_lb <- s1_iv_lb %>%
  raster::extract(y = st_coordinates(lb_pa_ch)) %>%
  cbind("PA" = lb_pa_ch$PA, .) %>%
  as.data.frame %>%
  na.omit 

s1_md_lb

save(s1_md_lb, file = "output/habitat_vars/s1_md_lb")
2.7.2.2.3 Scenario 1 future variables
s1_fv_lb <- s1_vars_landis_fut %>%
  sapply("[[", lblv) %>%
  mapply(clim_fv_4.5, FUN = stack)

save(s1_fv_lb, file = "output/habitat_vars/s1_fv_lb")

2.7.3 Scenario 2

awaiting updated climate variables

2.7.4 Scenario 3

2.7.4.1 Greater Glider

2.7.4.1.1 Scenario 3 initial variables
s3_iv_gg <- stack(s3_vars_landis_init[[c(gglv)]], clim_iv)

save(s3_iv_gg, file = "output/habitat_vars/s3_iv_gg")
2.7.4.1.2 Scenaio 3 model data
s3_md_gg <- s3_iv_gg %>%
  raster::extract(y = st_coordinates(gg_pa_ch)) %>%
  cbind("PA" = gg_pa_ch$PA, .) %>%
  as.data.frame %>%
  na.omit 

s3_md_gg

save(s3_md_gg, file = "output/habitat_vars/s3_md_gg")
2.7.4.1.3 Scenario 3 future variables
s3_fv_gg <- s3_vars_landis_fut %>%
  sapply("[[", gglv) %>%
  mapply(clim_fv_cc0, FUN = stack)

save(s3_fv_gg, file = "output/habitat_vars/s3_fv_gg")

2.7.4.2 Leadbeater’s Possum

2.7.4.2.1 Scenario 3 initial variables
s3_iv_lb <- stack(s3_vars_landis_init[[c(lblv)]], clim_iv)

save(s3_iv_lb, file = "output/habitat_vars/s3_iv_lb")
2.7.4.2.2 Scenaio 3 model data
s3_md_lb <- s3_iv_lb %>%
  raster::extract(y = st_coordinates(lb_pa_ch)) %>%
  cbind("PA" = lb_pa_ch$PA, .) %>%
  as.data.frame %>%
  na.omit 

s3_md_lb

save(s3_md_lb, file = "output/habitat_vars/s3_md_lb")
2.7.4.2.3 Scenario 3 future variables
s3_fv_lb <- s3_vars_landis_fut %>%
  sapply("[[", lblv) %>%
  mapply(clim_fv_cc0, FUN = stack)

save(s3_fv_lb, file = "output/habitat_vars/s3_fv_lb")

2.7.5 Scenario 4

2.7.5.1 Greater Glider

2.7.5.1.1 Scenario 4 initial variables
s4_iv_gg <- stack(s4_vars_landis_init[[c(gglv)]], clim_iv)

save(s4_iv_gg, file = "output/habitat_vars/s4_iv_gg")
2.7.5.1.2 Scenaio 4 model data
s4_md_gg <- s4_iv_gg %>%
  raster::extract(y = st_coordinates(gg_pa_ch)) %>%
  cbind("PA" = gg_pa_ch$PA, .) %>%
  as.data.frame %>%
  na.omit 

s4_md_gg

save(s4_md_gg, file = "output/habitat_vars/s4_md_gg")
2.7.5.1.3 Scenario 4 future variables
s4_fv_gg <- s4_vars_landis_fut %>%
  sapply("[[", gglv) %>%
  mapply(clim_fv_4.5, FUN = stack)

save(s4_fv_gg, file = "output/habitat_vars/s4_fv_gg")

2.7.5.2 Leadbeater’s Possum

2.7.5.2.1 Scenario 4 initial variables
s4_iv_lb <- stack(s4_vars_landis_init[[c(lblv)]], clim_iv)

save(s4_iv_lb, file = "output/habitat_vars/s4_iv_lb")
2.7.5.2.2 Scenaio 4 model data
s4_md_lb <- s4_iv_lb %>%
  raster::extract(y = st_coordinates(lb_pa_ch)) %>%
  cbind("PA" = lb_pa_ch$PA, .) %>%
  as.data.frame %>%
  na.omit 

s4_md_lb

save(s4_md_lb, file = "output/habitat_vars/s4_md_lb")
2.7.5.2.3 Scenario 4 future variables
s4_fv_lb <- s4_vars_landis_fut %>%
  sapply("[[", lblv) %>%
  mapply(clim_fv_4.5, FUN = stack)

save(s4_fv_lb, file = "output/habitat_vars/s4_fv_lb")

3 Distribution model fit and prediction

3.1 Greater Glider

3.1.1 Scenario 1

s1_mod_gg <- gbm.step(data = s1_md_gg, gbm.x = 2:8, gbm.y = 1, family = "bernoulli", tree.complexity = 5, learning.rate = 0.001, step.size = 1, bag.fraction = 0.5, prev.stratify = FALSE, verbose = FALSE, max.trees = 1000)
summary(s1_mod_gg)
#s1_ip_gg <- predict(s1_iv_gg, s1_mod_gg, type = "response", n.trees = s1_mod_gg$gbm.call$best.trees, filename = "output/habitat_pred/s1_fp_gg-000.tif")

#writeRaster(s1_ip_gg, "output/habitat_pred/s1_ip_gg.tif", overwrite = TRUE)
s1_ip_gg <- raster(x = "output/habitat_pred/s1_ip_gg.tif")

plot(s1_ip_gg)
registerDoMC(cores = 20)

s1_fp_gg <- foreach(i = seq_len(length(s1_fv_gg))) %dopar% {
  predict(s1_fv_gg[[i]],
          s1_mod_gg,
          type = "response",
          n.trees = s1_mod_gg$gbm.call$best.trees,
          filename = paste0("output/habitat_pred/s1_fp_gg-", sprintf("%03d", i), ".tif"),
          overwrite = TRUE)
}

s1_fp_gg <- stack(s1_fp_gg)
save(s1_fp_gg, file = "output/habitat_pred/s1_fp_gg")
writeRaster(s1_fp_gg, filename = "output/habitat_pred/s1_fp_gg.tif")

3.1.2 Scenario 3

s3_mod_gg <- gbm.step(data = s3_md_gg, gbm.x = 3:7, gbm.y = 1, family = "bernoulli", tree.complexity = 5, learning.rate = 0.001, step.size = 1, bag.fraction = 0.5, prev.stratify = FALSE, verbose = FALSE, max.trees = 1000)
summary(s3_mod_gg)
 # s3_ip_gg <- predict(s3_iv_gg, s3_mod_gg, type = "response", n.trees = s3_mod_gg$gbm.call$best.trees, filename ="output/habitat_pred/s3_fp_gg-000.tif")

 # writeRaster(s3_ip_gg, "output/habitat_pred/s3_ip_gg.tif", overwrite = TRUE)

s3_ip_gg <- raster(x = "output/habitat_pred/s3_ip_gg.tif")

plot(s3_ip_gg)
registerDoMC(cores = 20)

s3_fp_gg <- foreach(i = seq_len(length(s3_fv_gg))) %dopar% {
  predict(s3_fv_gg[[i]],
          s3_mod_gg,
          type = "response",
          n.trees = s3_mod_gg$gbm.call$best.trees,
          filename = paste0("output/habitat_pred/s3_fp_gg-", sprintf("%03d", i), ".tif"),
          overwrite = TRUE)
}

s3_fp_gg <- stack(s3_fp_gg)
save(s3_fp_gg, file = "output/habitat_pred/s3_fp_gg")
writeRaster(s3_fp_gg, filename = "output/habitat_pred/s3_fp_gg.tif")

3.1.3 Scenario 4

s4_mod_gg <- gbm.step(data = s4_md_gg, gbm.x = 2:8, gbm.y = 1, family = "bernoulli", tree.complexity = 5, learning.rate = 0.001, step.size = 1, bag.fraction = 0.5, prev.stratify = FALSE, verbose = FALSE, max.trees = 1000)
summary(s4_mod_gg)
# s4_ip_gg <- predict(s4_iv_gg, s4_mod_gg, type = "response", n.trees = s4_mod_gg$gbm.call$best.trees,  filename = "output/habitat_pred/4_fp_gg-000.tif")

# writeRaster(s4_ip_gg, "output/habitat_pred/s4_ip_gg.tif", overwrite = TRUE)

s4_ip_gg <- raster(x = "output/habitat_pred/s4_ip_gg.tif")

plot(s4_ip_gg)
registerDoMC(cores = 20)

s4_fp_gg <- foreach(i = seq_len(length(s4_fv_gg))) %dopar% {
  predict(s4_fv_gg[[i]],
          s4_mod_gg,
          type = "response",
          n.trees = s4_mod_gg$gbm.call$best.trees,
          filename = paste0("output/habitat_pred/s4_fp_gg-", sprintf("%03d", i), ".tif"),
          overwrite = TRUE)
}

s4_fp_gg <- stack(s4_fp_gg)
save(s4_fp_gg, file = "output/habitat_pred/s4_fp_gg")
writeRaster(s4_fp_gg, filename = "output/habitat_pred/s4_fp_gg.tif")

3.2 Leadbeater’s Possum

3.2.1 Scenario 1

s1_mod_lb <- gbm.step(data = s1_md_lb, gbm.x = 2:7, gbm.y = 1, family = "bernoulli", tree.complexity = 5, learning.rate = 0.001, step.size = 1, bag.fraction = 0.5, prev.stratify = FALSE, verbose = FALSE, max.trees = 1000)
summary(s1_mod_lb)
# s1_ip_lb <- predict(s1_iv_lb, s1_mod_lb, type = "response", n.trees = s1_mod_lb$gbm.call$best.trees, filename = "output/habitat_pred/s1_fp_lb-000.tif")

# writeRaster(s1_ip_lb, "output/habitat_pred/s1_ip_lb.tif", overwrite = TRUE)

s1_ip_lb <- raster(x = "output/habitat_pred/s1_ip_lb.tif")

plot(s1_ip_lb)
registerDoMC(cores = 20)

s1_fp_lb <- foreach(i = seq_len(length(s1_fv_lb))) %dopar% {
  predict(s1_fv_lb[[i]],
          s1_mod_lb,
          type = "response",
          n.trees = s1_mod_lb$gbm.call$best.trees,
          filename = paste0("output/habitat_pred/s1_fp_lb-", sprintf("%03d", i), ".tif"),
          overwrite = TRUE)
}

s1_fp_lb <- stack(s1_fp_lb)
save(s1_fp_lb, file = "output/habitat_pred/s1_fp_lb")
writeRaster(s1_fp_lb, filename = "output/habitat_pred/s1_fp_lb.tif")

3.2.2 Scenario 3

s3_mod_lb <- gbm.step(data = s3_md_lb, gbm.x = 2:7, gbm.y = 1, family = "bernoulli", tree.complexity = 5, learning.rate = 0.001, step.size = 1, bag.fraction = 0.5, prev.stratify = FALSE, verbose = FALSE, max.trees = 1000)
summary(s3_mod_lb)
# s3_ip_lb <- predict(s3_iv_lb, s3_mod_lb, type = "response", n.trees = s3_mod_lb$gbm.call$best.trees, filename = "output/habitat_pred/s3_fp_lb-000.tif")

# writeRaster(s3_ip_lb, "output/habitat_pred/s3_ip_lb.tif", overwrite = TRUE)

s3_ip_lb <- raster(x = "output/habitat_pred/s3_ip_lb.tif")

plot(s3_ip_lb)
registerDoMC(cores = 20)

s3_fp_lb <- foreach(i = seq_len(length(s3_fv_lb))) %dopar% {
  predict(s3_fv_lb[[i]],
          s3_mod_lb,
          type = "response",
          n.trees = s3_mod_lb$gbm.call$best.trees,
          filename = paste0("output/habitat_pred/s3_fp_lb-", sprintf("%03d", i), ".tif"),
          overwrite = TRUE)
}

s3_fp_lb <- stack(s3_fp_lb)
save(s3_fp_lb, file = "output/habitat_pred/s3_fp_lb")
writeRaster(s3_fp_lb, filename = "output/habitat_pred/s3_fp_lb.tif")

3.2.3 Scenario 4

s4_mod_lb <- gbm.step(data = s4_md_lb, gbm.x = 2:7, gbm.y = 1, family = "bernoulli", tree.complexity = 5, learning.rate = 0.001, step.size = 1, bag.fraction = 0.5, prev.stratify = FALSE, verbose = FALSE, max.trees = 1000)
summary(s4_mod_lb)
# s4_ip_lb <- predict(s4_iv_lb, s4_mod_lb, type = "response", n.trees = s4_mod_lb$gbm.call$best.trees, filename = "output/habitat_pred/s4_fp_lb-000.tif")

# writeRaster(s4_ip_lb, "output/habitat_pred/s4_ip_lb.tif", overwrite = TRUE)

s4_ip_lb <- raster(x = "output/habitat_pred/s4_ip_lb.tif")

plot(s4_ip_lb)
registerDoMC(cores = 20)

s4_fp_lb <- foreach(i = seq_len(length(s4_fv_lb))) %dopar% {
  predict(s4_fv_lb[[i]],
          s4_mod_lb,
          type = "response",
          n.trees = s4_mod_lb$gbm.call$best.trees,
          filename = paste0("output/habitat_pred/s4_fp_lb-", sprintf("%03d", i), ".tif"),
          overwrite = TRUE)
}

s4_fp_lb <- stack(s4_fp_lb)
save(s4_fp_lb, file = "output/habitat_pred/s4_fp_lb")
writeRaster(s4_fp_lb, filename = "output/habitat_pred/s4_fp_lb.tif")

4 Population viability analysis

4.1 Greater Glider

gg_trans_mat <- matrix(c(0.00,0.00,0.25,
                         0.50,0.00,0.00,
                         0.00,0.85,0.85),
                       nrow = 3, ncol = 3, byrow = TRUE) # based on Possingham et al 1994
colnames(gg_trans_mat) <- rownames(gg_trans_mat) <- c('Newborn','Juvenile','Adult')

gg_stable_states <- abs( eigen(gg_trans_mat)$vectors[,1] / base::sum(eigen(gg_trans_mat)$vectors[,1]) ) 

4.1.1 Scenario 1

s1_hs_gg <- stack(s1_ip_gg, s1_fp_gg)

for(i in 1:51){
  s1_hs_gg[[i]][is.na(s1_hs_gg[[i]][])] <- 0
}

s1_hs_gg <- mask(s1_hs_gg, mask = ch_mask)
s1_hab_k_gg <- calc(s1_hs_gg[[1]], fun = function(x){if(is.na(x)) x else rbinom(prob = x, size = 3, n = 1)})

names(s1_hab_k_gg) <- "carryingCapacity"

s1_gg_popN <- stack(replicate(ncol(gg_trans_mat), s1_hab_k_gg))

s1_gg_popN <- s1_gg_popN*gg_stable_states

s1_gg_idx <- which(!is.na(s1_hs_gg[[1]][]) & s1_hs_gg[[1]][] < 0.95)

s1_gg_pop <- s1_gg_popN
s1_gg_pop[!is.na(s1_gg_pop)] <- 0
s1_gg_pop[[1]][sample(s1_gg_idx, 10000)] <- 1
s1_gg_pop[[2]][sample(s1_gg_idx, 10000)] <- 1
s1_gg_pop[[3]][sample(s1_gg_idx, 10000)] <- 1

s1_gg_pop <- s1_gg_pop*ch_mask

names(s1_gg_pop) <- colnames(gg_trans_mat)

s1_gg_TotpopN <- sum(cellStats(s1_gg_pop, 'sum', na.rm = TRUE)) # Get total population size to check sensible
s1_gg_init_pop_size <- sum(s1_gg_pop)
s1_gg_landscape <- landscape(population = s1_gg_pop,
                          suitability = s1_hs_gg,
                          carrying_capacity = s1_hab_k_gg)

s1_gg_pop_dynamics <- population_dynamics(change = growth(transition_matrix = gg_trans_mat,
                                                       global_stochasticity = 0.1),
                                       dispersal = fast_dispersal(
                                         dispersal_kernel = exponential_dispersal_kernel(
                                           distance_decay = 8000)),
                                       modification = NULL)
plan(sequential, workers = 1)
s1_gg_results_1_50 <- simulation(landscape = s1_gg_landscape,
                         population_dynamics = s1_gg_pop_dynamics,
                         habitat_dynamics = NULL,
                         timesteps = 50,
                         replicates = 1)


saveRDS(object = s1_gg_results_1_50, file = "output/pva_results/s1_gg_results_1_50.Rds")
plot(s1_gg_results_1_50)
plot(s1_gg_results_1_50[1], type = "raster", stages = 0, timesteps = c(1:5))

4.1.2 Scenario 3

s3_hs_gg <- stack(s3_ip_gg, s3_fp_gg)

for(i in 1:51){
  s3_hs_gg[[i]][is.na(s3_hs_gg[[i]][])] <- 0
}

s3_hs_gg <- mask(s3_hs_gg, mask = ch_mask)
s3_hab_k_gg <- calc(s3_hs_gg[[1]], fun = function(x){if(is.na(x)) x else rbinom(prob = x, size = 3, n = 1)})

names(s3_hab_k_gg) <- "carryingCapacity"

s3_gg_popN <- stack(replicate(ncol(gg_trans_mat), s3_hab_k_gg))

s3_gg_popN <- s3_gg_popN*gg_stable_states

s3_gg_idx <- which(!is.na(s3_hs_gg[[1]][]) & s3_hs_gg[[1]][] < 0.95)

s3_gg_pop <- s3_gg_popN
s3_gg_pop[!is.na(s3_gg_pop)] <- 0
s3_gg_pop[[1]][sample(s3_gg_idx, 10000)] <- 1
s3_gg_pop[[2]][sample(s3_gg_idx, 10000)] <- 1
s3_gg_pop[[3]][sample(s3_gg_idx, 10000)] <- 1

s3_gg_pop <- s3_gg_pop*ch_mask

names(s3_gg_pop) <- colnames(gg_trans_mat)

s3_gg_TotpopN <- sum(cellStats(s3_gg_pop, 'sum', na.rm = TRUE)) # Get total population size to check sensible
s3_gg_init_pop_size <- sum(s3_gg_pop)
s3_gg_landscape <- landscape(population = s3_gg_pop,
                          suitability = s3_hs_gg,
                          carrying_capacity = s3_hab_k_gg)

s3_gg_pop_dynamics <- population_dynamics(change = growth(transition_matrix = gg_trans_mat,
                                                       global_stochasticity = 0.1),
                                       dispersal = fast_dispersal(
                                         dispersal_kernel = exponential_dispersal_kernel(
                                           distance_decay = 8000)),
                                       modification = NULL)
plan(sequential, workers = 1)
s3_gg_results_1_50 <- simulation(landscape = s3_gg_landscape,
                         population_dynamics = s3_gg_pop_dynamics,
                         habitat_dynamics = NULL,
                         timesteps = 50,
                         replicates = 1)


saveRDS(object = s3_gg_results_1_50, file = "output/pva_results/s3_gg_results_1_50.Rds")
plot(s3_gg_results_1_50)
plot(s3_gg_results_1_50[1], type = "raster", stages = 0, timesteps = c(1:5))

4.1.3 Scenario 4

s4_hs_gg <- stack(s4_ip_gg, s4_fp_gg)

for(i in 1:51){
  s4_hs_gg[[i]][is.na(s4_hs_gg[[i]][])] <- 0
}

s4_hs_gg <- mask(s4_hs_gg, mask = ch_mask)
s4_hab_k_gg <- calc(s4_hs_gg[[1]], fun = function(x){if(is.na(x)) x else rbinom(prob = x, size = 3, n = 1)})

names(s4_hab_k_gg) <- "carryingCapacity"

s4_gg_popN <- stack(replicate(ncol(gg_trans_mat), s4_hab_k_gg))

s4_gg_popN <- s4_gg_popN*gg_stable_states

s4_gg_idx <- which(!is.na(s4_hs_gg[[1]][]) & s4_hs_gg[[1]][] < 0.95)

s4_gg_pop <- s4_gg_popN
s4_gg_pop[!is.na(s4_gg_pop)] <- 0
s4_gg_pop[[1]][sample(s4_gg_idx, 10000)] <- 1
s4_gg_pop[[2]][sample(s4_gg_idx, 10000)] <- 1
s4_gg_pop[[3]][sample(s4_gg_idx, 10000)] <- 1

s4_gg_pop <- s4_gg_pop*ch_mask

names(s4_gg_pop) <- colnames(gg_trans_mat)

s4_gg_TotpopN <- sum(cellStats(s4_gg_pop, 'sum', na.rm = TRUE)) # Get total population size to check sensible
s4_gg_init_pop_size <- sum(s4_gg_pop)
s4_gg_landscape <- landscape(population = s4_gg_pop,
                          suitability = s4_hs_gg,
                          carrying_capacity = s4_hab_k_gg)

s4_gg_pop_dynamics <- population_dynamics(change = growth(transition_matrix = gg_trans_mat,
                                                       global_stochasticity = 0.1),
                                       dispersal = fast_dispersal(
                                         dispersal_kernel = exponential_dispersal_kernel(
                                           distance_decay = 8000)),
                                       modification = NULL)
plan(sequential, workers = 1)
s4_gg_results_1_50 <- simulation(landscape = s4_gg_landscape,
                         population_dynamics = s4_gg_pop_dynamics,
                         habitat_dynamics = NULL,
                         timesteps = 50,
                         replicates = 1)


saveRDS(object = s4_gg_results_1_50, file = "output/pva_results/s4_gg_results_1_50.Rds")
plot(s4_gg_results_1_50)
plot(s4_gg_results_1_50[1], type = "raster", stages = 0, timesteps = c(1:5))

4.2 Leadbeater’s Possum

lb_trans_mat <- matrix(c(0.00, 0.00, 1.10,
                         0.59, 0.00, 0.00,
                         0.00, 0.59, 0.79),
                       nrow = 3, ncol = 3, byrow = TRUE) 
colnames(lb_trans_mat) <- rownames(lb_trans_mat) <- c('Newborn','Juvenile','Adult')

lb_stable_states <- abs( eigen(lb_trans_mat)$vectors[,1] / base::sum(eigen(lb_trans_mat)$vectors[,1]) ) 

4.2.1 Scenario 1

s1_hs_lb <- stack(s1_ip_lb, s1_fp_lb)

for(i in 1:51){
  s1_hs_lb[[i]][is.na(s1_hs_lb[[i]][])] <- 0
}

s1_hs_lb <- mask(s1_hs_lb, mask = ch_mask)
s1_hab_k_lb <- calc(s1_hs_lb[[1]], fun = function(x){if(is.na(x)) x else rbinom(prob = x, size = 3, n = 1)})

names(s1_hab_k_lb) <- "carryingCapacity"

s1_lb_popN <- stack(replicate(ncol(lb_trans_mat), s1_hab_k_lb))

s1_lb_popN <- s1_lb_popN*lb_stable_states

s1_lb_idx <- which(!is.na(s1_hs_lb[[1]][]) & s1_hs_lb[[1]][] < 0.95)

s1_lb_pop <- s1_lb_popN
s1_lb_pop[!is.na(s1_lb_pop)] <- 0
s1_lb_pop[[1]][sample(s1_lb_idx, 3000)] <- 1
s1_lb_pop[[2]][sample(s1_lb_idx, 3000)] <- 1
s1_lb_pop[[3]][sample(s1_lb_idx, 3000)] <- 1

s1_lb_pop <- s1_lb_pop*ch_mask

names(s1_lb_pop) <- colnames(lb_trans_mat)

s1_lb_TotpopN <- sum(cellStats(s1_lb_pop, 'sum', na.rm = TRUE)) # Get total population size to check sensible
s1_lb_init_pop_size <- sum(s1_lb_pop)
s1_lb_landscape <- landscape(population = s1_lb_pop,
                          suitability = s1_hs_lb,
                          carrying_capacity = s1_hab_k_lb)

s1_lb_pop_dynamics <- population_dynamics(change = growth(transition_matrix = lb_trans_mat,
                                                       global_stochasticity = 0.3),
                                       dispersal = fast_dispersal(
                                         dispersal_kernel = exponential_dispersal_kernel(
                                           distance_decay = 2000)),
                                       modification = NULL)
plan(sequential, workers = 1)
s1_lb_results_1_50 <- simulation(landscape = s1_lb_landscape,
                         population_dynamics = s1_lb_pop_dynamics,
                         habitat_dynamics = NULL,
                         timesteps = 50,
                         replicates = 1)


saveRDS(object = s1_lb_results_1_50, file = "output/pva_results/s1_lb_results_1_50.Rds")
plot(s1_lb_results_1_50)
plot(s1_lb_results_1_50[1], type = "raster", stages = 0, timesteps = c(1:5))

4.2.2 Scenario 3

s3_hs_lb <- stack(s3_ip_lb, s3_fp_lb)

for(i in 1:51){
  s3_hs_lb[[i]][is.na(s3_hs_lb[[i]][])] <- 0
}

s3_hs_lb <- mask(s3_hs_lb, mask = ch_mask)
s3_hab_k_lb <- calc(s3_hs_lb[[1]], fun = function(x){if(is.na(x)) x else rbinom(prob = x, size = 3, n = 1)})

names(s3_hab_k_lb) <- "carryingCapacity"

s3_lb_popN <- stack(replicate(ncol(lb_trans_mat), s3_hab_k_lb))

s3_lb_popN <- s3_lb_popN*lb_stable_states

s3_lb_idx <- which(!is.na(s3_hs_lb[[1]][]) & s3_hs_lb[[1]][] < 0.95)

s3_lb_pop <- s3_lb_popN
s3_lb_pop[!is.na(s3_lb_pop)] <- 0
s3_lb_pop[[1]][sample(s3_lb_idx, 3000)] <- 1
s3_lb_pop[[2]][sample(s3_lb_idx, 3000)] <- 1
s3_lb_pop[[3]][sample(s3_lb_idx, 3000)] <- 1

s3_lb_pop <- s3_lb_pop*ch_mask

names(s3_lb_pop) <- colnames(lb_trans_mat)

s3_lb_TotpopN <- sum(cellStats(s3_lb_pop, 'sum', na.rm = TRUE)) # Get total population size to check sensible
s3_lb_init_pop_size <- sum(s3_lb_pop)
s3_lb_landscape <- landscape(population = s3_lb_pop,
                          suitability = s3_hs_lb,
                          carrying_capacity = s3_hab_k_lb)

s3_lb_pop_dynamics <- population_dynamics(change = growth(transition_matrix = lb_trans_mat,
                                                       global_stochasticity = 0.1),
                                       dispersal = fast_dispersal(
                                         dispersal_kernel = exponential_dispersal_kernel(
                                           distance_decay = 8000)),
                                       modification = NULL)
plan(sequential, workers = 1)
s3_lb_results_1_50 <- simulation(landscape = s3_lb_landscape,
                         population_dynamics = s3_lb_pop_dynamics,
                         habitat_dynamics = NULL,
                         timesteps = 50,
                         replicates = 1)


saveRDS(object = s3_lb_results_1_50, file = "output/pva_results/s3_lb_results_1_50.Rds")
plot(s3_lb_results_1_50)
plot(s3_lb_results_1_50[1], type = "raster", stages = 0, timesteps = c(1:5))

4.2.3 Scenario 4

s4_hs_lb <- stack(s4_ip_lb, s4_fp_lb)

for(i in 1:51){
  s4_hs_lb[[i]][is.na(s4_hs_lb[[i]][])] <- 0
}

s4_hs_lb <- mask(s4_hs_lb, mask = ch_mask)
s4_hab_k_lb <- calc(s4_hs_lb[[1]], fun = function(x){if(is.na(x)) x else rbinom(prob = x, size = 3, n = 1)})

names(s4_hab_k_lb) <- "carryingCapacity"

s4_lb_popN <- stack(replicate(ncol(lb_trans_mat), s4_hab_k_lb))

s4_lb_popN <- s4_lb_popN*lb_stable_states

s4_lb_idx <- which(!is.na(s4_hs_lb[[1]][]) & s4_hs_lb[[1]][] < 0.95)

s4_lb_pop <- s4_lb_popN
s4_lb_pop[!is.na(s4_lb_pop)] <- 0
s4_lb_pop[[1]][sample(s4_lb_idx, 3000)] <- 1
s4_lb_pop[[2]][sample(s4_lb_idx, 3000)] <- 1
s4_lb_pop[[3]][sample(s4_lb_idx, 3000)] <- 1

s4_lb_pop <- s4_lb_pop*ch_mask

names(s4_lb_pop) <- colnames(lb_trans_mat)

s4_lb_TotpopN <- sum(cellStats(s4_lb_pop, 'sum', na.rm = TRUE)) # Get total population size to check sensible
s4_lb_init_pop_size <- sum(s4_lb_pop)
s4_lb_landscape <- landscape(population = s4_lb_pop,
                          suitability = s4_hs_lb,
                          carrying_capacity = s4_hab_k_lb)

s4_lb_pop_dynamics <- population_dynamics(change = growth(transition_matrix = lb_trans_mat,
                                                       global_stochasticity = 0.1),
                                       dispersal = fast_dispersal(
                                         dispersal_kernel = exponential_dispersal_kernel(
                                           distance_decay = 8000)),
                                       modification = NULL)
plan(sequential, workers = 1)
s4_lb_results_1_50 <- simulation(landscape = s4_lb_landscape,
                         population_dynamics = s4_lb_pop_dynamics,
                         habitat_dynamics = NULL,
                         timesteps = 50,
                         replicates = 1)


saveRDS(object = s4_lb_results_1_50, file = "output/pva_results/s4_lb_results_1_50.Rds")
plot(s4_lb_results_1_50)
plot(s4_lb_results_1_50[1], type = "raster", stages = 0, timesteps = c(1:5))
LS0tCnRpdGxlOiAiVmljdG9yaWFuIEZvcmVzdCBGdXR1cmVzIFBvcHVsYXRpb24gVmFiaWxpdHkgQW5hbHlzaXM6IENlbnRyYWwgSGlnaGxhbmRzIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6IAogICAgdG9jOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQphdXRob3I6IEdFIFJ5YW4KZGF0ZTogMjAxOS0wOC0wNQotLS0KCiMgUHJvamVjdCBzZXR1cAoKIyMjIFBhY2thZ2VzCkluc3RhbGwgcGFja2FnZXMgaWYgbmVjZXNzYXJ5LiBMaXN0ZWQgYXJlIGluc3RhbGxlcnMgZm9yIHBhY2thZ2VzIG5vdCBvbiBDUkFOIGFuZCB0aGUgZGV2bG9wbWVudCAobW9zdCB1cC10by1kYXRlKSB2ZXJzaW9uIG9mIFNURVBTLgpgYGB7ciBpbnN0YWxsIHBhY2thZ2VzfQojIGxpYnJhcnkoZGV2dG9vbHMpCiMgaW5zdGFsbF9naXRodWIoInN0ZXBzLWRldi9zdGVwcyIpCiMgaW5zdGFsbF9naXRodWIoInNtd2luZGVja2VyL2dkYWx0b29scyIpCmBgYAoKTG9hZCBwYWNrYWdlcwpgYGB7ciBwYWNrYWdlc30KbGlicmFyeShyYXN0ZXIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGliYmxlKQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KHJnZGFsKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShmb3JlYWNoKQpsaWJyYXJ5KGRvTUMpCmxpYnJhcnkoZnV0dXJlKQpsaWJyYXJ5KGZ1dHVyZS5hcHBseSkKbGlicmFyeSh0aWR5cikKbGlicmFyeShkaXNtbykKbGlicmFyeShnYm0pCmxpYnJhcnkoc3RlcHMpCmxpYnJhcnkoZ2RhbHRvb2xzKQpgYGAKCiMjIyBGdW5jdGlvbnMKYGBge3IgZnVuY3Rpb25zfQpzb3VyY2UoZmlsZSA9ICJSL2Z1bmN0aW9ucy9wZy5zZi5SIikKc291cmNlKGZpbGUgPSAiUi9mdW5jdGlvbnMvcGcucGEuUiIpCnNvdXJjZShmaWxlID0gIlIvZnVuY3Rpb25zL3JlYWQudmJhLlIiKQpzb3VyY2UoZmlsZSA9ICJSL2Z1bmN0aW9ucy9wcm9jLnZiYS5SIikKc291cmNlKGZpbGUgPSAiUi9mdW5jdGlvbnMvZ2V0LmxhbmRpcy52YXJzLlIiKQpzb3VyY2UoZmlsZSA9ICJSL2Z1bmN0aW9ucy9yYXNjYy5SIikKc291cmNlKGZpbGUgPSAiUi9mdW5jdGlvbnMvcmVhZC5tdWx0aS5saW5lLmhlYWRlci5SIikKc291cmNlKGZpbGUgPSAiUi9mdW5jdGlvbnMvaW50ZXJwb2xhdGUuY2xpbWRhdC5SIikKc291cmNlKGZpbGUgPSAiUi9mdW5jdGlvbnMvZ2V0LnJzdC5wcm9wLlIiKQpzb3VyY2UoZmlsZSA9ICJSL2Z1bmN0aW9ucy9nZXQucnN0LmRhdC5SIikKYGBgCgojIyMgUGF0aHMKYGBge3IgcGF0aHN9CnByb2pfcGF0aCA8LSAiL2hvbWUvbGFuZGlzL3Jmc3QvIgojIHByb2pfcGF0aCA8LSAiRDovVXNlcnMvcnlhbi9Ecm9wYm94L1dvcmsvUkZBX1NURVBTL3Jmc3QvIgpgYGAKCgojIFByZXBhcmUgdmFyaWFibGVzCgojIyBBbmFseXNpcyBwYXJhbWV0ZXJzCgojIyMgVGltZXN0ZXBzCmBgYHtyIG50aW1lc3RlcHN9Cm50aW1lc3RlcHMgPC0gNTAKYGBgCgpgYGB7ciBuY29yZXN9Cm5jb3JlcyA8LSAyMApgYGAKCgoKIyMgR2VvZ3JhcGhpYyBkYXRhCgojIyMgTGFuZHNjYXBlClNldCB1cCBiYXNlIGxhbmRzY2FwZSBsYXllcgpgYGB7ciBjaF9yc3R9CmNoX3JzdCA8LSByYXN0ZXIoeCA9ICJkYXRhL2dyaWRzL2Vjb192MTIuaW1nIikgJVQ+JQogIHBsb3QKYGBgCgpgYGB7ciBwcm9qIGV4dCByZXN9CmNoX3Byb2ogPC0gY2hfcnN0QGNycwpjaF9leHRlbnQgPC0gZXh0ZW50KGNoX3JzdCkKY2hfcmVzIDwtIHJlcyhjaF9yc3QpCmBgYAoKIyMjIEJvdW5kYXJpZXMKYGBge3IgcmZhfQpyZmEgPC0gcmVhZF9zZigiZGF0YS9zaGFwZWZpbGVzL1JGQS8iKSU+JQogIHN0X3RyYW5zZm9ybShjcnMgPSBjaF9wcm9qKQpyZmEKYGBgCgpgYGB7ciBwbG90IHJmYX0KcGcuc2YocmZhKQpgYGAKCmBgYHtyIGNoX3JmYX0KY2hfcmZhIDwtIHJmYVtyZmEkTkFNRT09ICJDRU5UUkFMIEhJR0hMQU5EUyIsXSAKCmNoX3JmYQpgYGAKCmBgYHtyIHBsb3QgY2hfcmZhfQpwZy5zZihjaF9yZmEpCmBgYAoKCmBgYHtyIGNoX21hc2t9CmNoX21hc2sgPC0gcmFzdGVyaXplKGNoX3JmYSwgY2hfcnN0LCBmaWVsZCA9IDEsIGZpbGVuYW1lID0gIi4vb3V0cHV0L2xhbmRzY2FwZV92YXJzL2NoX21hc2suZ3JkIiwgb3ZlcndyaXRlID0gVFJVRSkgCgpjaF9tYXNrW2NoX3JzdCA9PSAxMzJdIDwtIE5BICMgcmVtb3ZlcyBsYWtlIGFyZWFzIGZyb20gaGFiaXRhdAoKcGxvdChjaF9tYXNrKQpgYGAKKlRoaW5rIGNhcmVmdWxseSBhYm91dCB1c2luZyB0aGlzIGxheWVyIGFzIHByb2plY3Rpb25zIGFyZSBmb3Igem9uZSA1NSwgc28gZGlzdG9ydHMgd2VzdCBvZiB0aGUgc3RhdGUqCmBgYHtyIHZpY3RvcmlhfQp2aWN0b3JpYSA8LSByZWFkX3NmKCJkYXRhL3NoYXBlZmlsZXMvdmljc3RhdGVwb2x5Z29uLyIpICU+JQogICBzdF90cmFuc2Zvcm0oY3JzID0gY2hfcHJvaikKYGBgCgoKCgojIyBPY2N1cnJlbmNlIGRhdGEKCmBgYHtyIHBzZXVkb19hYnN9CnBzZXVkb19hYnMgPC0gcmVhZF9zZigiZGF0YS9zaGFwZWZpbGVzL3BzZXVkb19hYnNlbmNlcy9wc2V1ZG9fYWJzZW5jZXMuc2hwIiklPiUKICBzdF90cmFuc2Zvcm0oY3JzID0gc3RfY3JzKGNoX3JzdCkpICU+JQogIG11dGF0ZShQQSA9IDApICU+JQogIHNlbGVjdChQQSwgZ2VvbWV0cnkpICU+JQogIHN0X3ptKGRyb3AgPSBUUlVFKQoKcHNldWRvX2FicwpgYGAKCgojIyMgR0cgT2NjdXJyZW5jZSBkYXRhClJlYWQgaW4gZGF0YQpgYGB7ciBnZ19hcml9CmdnX2FyaSA8LSByZWFkX2V4Y2VsKHBhdGggPSAiZGF0YS90YWJ1bGFyL0JvQV9TQl9Db21iaW5lZF9WQkFfdXBsb2FkX3Y0LnhscyIpICU+JQogIGRwbHlyOjpzZWxlY3QoLXN0YXJ0c193aXRoKCJsZWF2ZSIpKSAlPiUKICByZW5hbWUoImxvbiIgPSBgWC1jb29yZGluYXRlIChlYXN0aW5nIG9yIGxvbmdpdHVkZSlgLCAibGF0IiA9IGBZLWNvb3JkaW5hdGUgKG5vcnRoaW5nIG9yIGxhdGl0dWRlKWApICU+JQogICBmaWxsKGxvbiwgbGF0LCAuZGlyZWN0aW9uID0gImRvd24iKSAlPiUKICBmaWx0ZXIoYFRheG9uIE5hbWVgID09ICJNaXNjIFRhcmdldCB0YXhhIG5vdCBmb3VuZCIpICU+JQogIHNlbGVjdChsb24sIGxhdCkgJT4lCiAgbXV0YXRlKFBBID0gMCkgJT4lCiAgc3RfYXNfc2YoY29vcmRzID0gYygibG9uIiwgImxhdCIpLCBjcnMgPSBzdF9jcnMoMjgzNTUpKSAlPiUKICBzdF90cmFuc2Zvcm0oY3JzID0gc3RfY3JzKGNoX3JzdCkpCgpnZ19hcmkKYGBgCgpgYGB7ciBnZ192YmF9CmdnX3ZiYSA8LSBwcm9jLnZiYSgiZGF0YS90YWJ1bGFyL3ZiYV9nZ19hbGxfMjAxOTA1MDkuY3N2IiwgcHJvamVjdC5jcnMgPSBjaF9wcm9qKQoKZ2dfdmJhCmBgYAoKYGBge3IgZ2dfcGFfYWxsfQpnZ19wYV9hbGwgPC0gZ2dfdmJhICU+JQogIHJiaW5kKGdnX2FyaSkKCmdnX3BhX2FsbApgYGAKCmBgYHtyIHBsb3RfZ2dfcGFfYWxsfQpwbG90X2dnX3BhX2FsbCA8LSBwZy5wYShnZ19wYV9hbGwsIGNoX3JmYSkgKwogIGdlb21fc2YoZGF0YSA9IHZpY3RvcmlhLCBmaWxsID0gTkEpCgpwbG90X2dnX3BhX2FsbApgYGAKCmBgYHtyIGdnX3BhX2NofQpnZ19wYV9jaCA8LSBnZ19wYV9hbGxbY2hfcmZhLF0KZ2dfcGFfY2gKYGBgCgpgYGB7ciBnZ19wYV9jaF9wc2FifQpnZ19wYV9jaF9wc2FiIDwtIGdnX3BhX2NoICU+JQogIHJiaW5kKHBzZXVkb19hYnMpCmBgYAoKCmBgYHtyIHdyaXRlIGdnX3BhX2NofQpzdF93cml0ZShnZ19wYV9jaCwgIm91dHB1dC9zaGFwZWZpbGVzL3BhL2NoL2dnX3BhX2NoLnNocCIsIGRlbGV0ZV9sYXllciA9IFRSVUUpCnN0X3dyaXRlKGdnX3BhX2NoX3BzYWIsICJvdXRwdXQvc2hhcGVmaWxlcy9wYS9jaC9nZ19wYV9jaF9wc2FiLnNocCIsIGRlbGV0ZV9sYXllciA9IFRSVUUpCmBgYAoKCmBgYHtyIHBnX2dnX3BhX2NofQpwZ19nZ19wYV9jaCA8LSBwZy5wYShnZ19wYV9jaCAlPiUgbXV0YXRlKHBzZXVkb19hYnMgPSAidmJhIikgJT4lIHJiaW5kKHBzZXVkb19hYnMgJT4lIG11dGF0ZShwc2V1ZG9fYWJzID0gInBzZXVkb19hYnNlbmNlcyIpKSwgY2hfcmZhKSArCiAgZmFjZXRfZ3JpZCgufnBzZXVkb19hYnMpCgpwZ19nZ19wYV9jaApgYGAKCiMjIyBMQlAgT2NjdXJyZW5jZSBkYXRhCmBgYHtyIHJlYWQgbGIgb2NjfQpsYl9wYV9hbGwgPC0gcHJvYy52YmEoImRhdGEvdGFidWxhci92YmFfbGJfYWxsXzIwMTkwNTA5LmNzdiIsIHByb2plY3QuY3JzID0gY2hfcHJvaikKYGBgCgpgYGB7ciBwbG90X2xiX3BhX2FsbH0KcGxvdF9sYl9wYV9hbGwgPC0gcGcucGEobGJfcGFfYWxsLCBjaF9yZmEpICsKICBnZW9tX3NmKGRhdGEgPSB2aWN0b3JpYSwgZmlsbCA9IE5BKQoKcGxvdF9sYl9wYV9hbGwKYGBgCgpgYGB7ciBsYl9wYV9jaH0KbGJfcGFfY2ggPC0gbGJfcGFfYWxsW2NoX3JmYSxdCmxiX3BhX2NoCmBgYAoKYGBge3IgbGJfcGFfY2hfcHNhYn0KbGJfcGFfY2hfcHNhYiA8LSBsYl9wYV9jaCAlPiUKICByYmluZChwc2V1ZG9fYWJzKQpgYGAKCgpgYGB7ciB3cml0ZSBsYnBfcGFfY2h9CnN0X3dyaXRlKGxiX3BhX2NoLCAib3V0cHV0L3NoYXBlZmlsZXMvcGEvY2gvbGJfcGFfY2guc2hwIiwgZGVsZXRlX2xheWVyID0gVFJVRSkKc3Rfd3JpdGUobGJfcGFfY2hfcHNhYiwgIm91dHB1dC9zaGFwZWZpbGVzL3BhL2NoL2xiX3BhX2NoX3BzYWIuc2hwIiwgZGVsZXRlX2xheWVyID0gVFJVRSkKYGBgCgoKYGBge3IgcGdfbGJfcGFfY2h9CnBnX2xiX3BhX2NoIDwtIHBnLnBhKGxiX3BhX2NoICU+JSBtdXRhdGUocHNldWRvX2FicyA9ICJ2YmEiKSAlPiUgcmJpbmQocHNldWRvX2FicyAlPiUgbXV0YXRlKHBzZXVkb19hYnMgPSAicHNldWRvX2Fic2VuY2VzIikpLCBjaF9yZmEpICsKICBmYWNldF9ncmlkKC5+cHNldWRvX2FicykKCnBnX2xiX3BhX2NoCmBgYAoKYGBge3Igc2F2ZSBpbWFnZSBvY2N1fQpzYXZlLmltYWdlKCJvdXRwdXQvc2Vzc2lvbl9pbWFnZXMvbGFuZHNjYXBlLW9jY3VwYW5jeS5SRGF0YSIpCmBgYAoKYGBge3IgbG9hZCBpbWFnZSBvY2N1fQojbG9hZChmaWxlID0gIm91dHB1dC9zZXNzaW9uX2ltYWdlcy9sYW5kc2NhcGUtb2NjdXBhbmN5LlJEYXRhIikKYGBgCgoKIyMgTGFuZGlzIG91dHB1dAoKIyMjIFNjZW5hcmlvIDE6IEN1cnJlbnQgcGxhbm5lZCBidXJuaW5nLCBjdXJyZW50IHRpbWJlciBoYXJ2ZXN0aW5nLCBjbGltYXRlIGNoYW5nZSB1bmRlciBSQ1AgNC41LCBjdXJyZW50IGJ1c2hmaXJlIHJlZ2ltZSAoQnVpc25lc3MgYXMgdXN1YWwpCgpgYGB7cn0KYWEgPC0gZ2V0LmxhbmRpcy52YXJzKAogIHNjbl9wYXRoID0gIn4vbGFuZGlzX2NoX3MxX3BiLXRoLWNjXzUwLyIsCiAgcHJval9wYXRoID0gcHJval9wYXRoLAogIG91dF9wYXRoID0gIi9vdXRwdXQvaGFiaXRhdF92YXJzLyIsCiAgc2NuX2lkID0gInMxIiwKICBwcm9qX21hc2sgPSBjaF9tYXNrLAogIHRpbWVzdGVwcyA9IDMsCiAgY29yZXMgPSA0CiAgKQpgYGAKCmBgYHtyfQpwbG90KGFhW1s0XV0pCmBgYAoKYGBge3IgcGxvdCBzMV92YXJzX2xhbmRpcyBsYXN0fQpwbG90KHMxX3ZhcnNfbGFuZGlzW1tudGltZXN0ZXBzICsgMV1dKQpgYGAKCgpgYGB7ciBzMV92YXJzX2xhbmRpcyBzYXZlIGxvYWR9CnNhdmUoczFfdmFyc19sYW5kaXMsIGZpbGUgPSAib3V0cHV0L2hhYml0YXRfdmFycy9zMV92YXJzX2xhbmRpcyIpCgojIGxvYWQoZmlsZSA9ICJvdXRwdXQvaGFiaXRhdF92YXJzL3MxX3ZhcnNfbGFuZGlzX2Z1dCIpCmBgYAoKCiMjIyBTY2VuYXJpbyAyOiBDdXJyZW50IHBsYW5uZWQgYnVybmluZywgY3VycmVudCB0aW1iZXIgaGFydmVzdGluZywgY2xpbWF0ZSBjaGFuZ2UgdW5kZXIgUkNQIDguNSwgaW5jcmVhdHJlZCBidXNoZmlyZSByZWdpbWUKCgojIyMgU2NlbmFyaW8gMzogQ3VycmVudCBwbGFubmVkIGJ1cm5pbmcsIGN1cnJlbnQgdGltYmVyIGhhcnZlc3RpbmcsIG5vIGNsaW1hdGUgY2hhbmdlLCBjdXJyZW50IGJ1c2hmaXJlIHJlZ2ltZQpgYGB7ciBzM192YXJzX2xhbmRpc30KczNfdmFyc19sYW5kaXMgPC0gZ2V0LmxhbmRpcy52YXJzKAogIHNjbl9wYXRoID0gIn4vbGFuZGlzX2NoX3MzX3BiLXRoLWNjMF81MC8iLAogIHByb2pfcGF0aCA9IHByb2pfcGF0aCwKICBvdXRfcGF0aCA9ICIvb3V0cHV0L2hhYml0YXRfdmFycy8iLAogIHNjbl9pZCA9ICJzMyIsCiAgcHJval9tYXNrID0gY2hfbWFzaywKICB0aW1lc3RlcHMgPSBudGltZXN0ZXBzLAogIGNvcmVzID0gbmNvcmVzCiAgKQpgYGAKCmBgYHtyIHBsb3QgczNfdmFyc19sYW5kaXMgaW5pdGlhbH0KcGxvdChzM192YXJzX2xhbmRpc1tbMV1dKQpgYGAKCmBgYHtyIHBsb3QgczNfdmFyc19sYW5kaXMgbGFzdH0KcGxvdChzM192YXJzX2xhbmRpc1tbbnRpbWVzdGVwcyArIDFdXSkKYGBgCgoKYGBge3IgczNfdmFyc19sYW5kaXMgc2F2ZSBsb2FkfQpzYXZlKHMzX3ZhcnNfbGFuZGlzLCBmaWxlID0gIm91dHB1dC9oYWJpdGF0X3ZhcnMvczNfdmFyc19sYW5kaXMiKQoKIyBsb2FkKGZpbGUgPSAib3V0cHV0L2hhYml0YXRfdmFycy9zM192YXJzX2xhbmRpc19mdXQiKQpgYGAKCiMjIyBTY2VuYXJpbyA0OiBDdXJyZW50IHBsYW5uZWQgYnVybmluZywgbm8gaGFydmVzdGluZywgY2xpbWF0ZSBjaGFuZ2UgdW5kZXIgUkNQIDQuNSwgY3VycmVudCBidXNoZmlyZSByZWdpbWUKYGBge3IgczRfdmFyc19sYW5kaXN9CnM0X3ZhcnNfbGFuZGlzIDwtIGdldC5sYW5kaXMudmFycygKICBzY25fcGF0aCA9ICJ+L2xhbmRpc19jaF9zNF9wYi10aDAtY2NfNTAvIiwKICBwcm9qX3BhdGggPSBwcm9qX3BhdGgsCiAgb3V0X3BhdGggPSAiL291dHB1dC9oYWJpdGF0X3ZhcnMvIiwKICBzY25faWQgPSAiczQiLAogIHByb2pfbWFzayA9IGNoX21hc2ssCiAgdGltZXN0ZXBzID0gbnRpbWVzdGVwcywKICBjb3JlcyA9IG5jb3JlcywKICBoYXJ2ZXN0X3RpbWJlciA9IEZBTFNFCiAgKQpgYGAKCmBgYHtyIHBsb3QgczRfdmFyc19sYW5kaXMgaW5pdGlhbH0KcGxvdChzNF92YXJzX2xhbmRpc1tbMV1dKQpgYGAKCmBgYHtyIHBsb3QgczRfdmFyc19sYW5kaXMgbGFzdH0KcGxvdChzNF92YXJzX2xhbmRpc1tbbnRpbWVzdGVwcyArIDFdXSkKYGBgCgoKYGBge3IgczRfdmFyc19sYW5kaXMgc2F2ZSBsb2FkfQpzYXZlKHM0X3ZhcnNfbGFuZGlzLCBmaWxlID0gIm91dHB1dC9oYWJpdGF0X3ZhcnMvczRfdmFyc19sYW5kaXMiKQoKIyBsb2FkKGZpbGUgPSAib3V0cHV0L2hhYml0YXRfdmFycy9zNF92YXJzX2xhbmRpc19mdXQiKQpgYGAKCiMjIEFSSSBEYXRhCgojIyMgQW5pc290cm9uaWMgaGVhdGluZyB4IHJ1Z2dlZG5lc3MKYGBge3IgYWhyfQphaHIgPC1yYXN0ZXIoeCA9ICJkYXRhL2dyaWRzL0Vudl9jb3ZhcmlhdGVzX25vQ2xpbWF0ZV9WaWNHcmlkOTQvQW5pc290cm9waGljX0hlYXRpbmdfUnVnZ2VkbmVzcyIpICU+JQogIHByb2plY3RSYXN0ZXIodG8gPSBjaF9tYXNrKSAlPiUKICBtYXNrKG1hc2sgPSBjaF9tYXNrLCBmaWxlbmFtZSA9ICJvdXRwdXQvaGFiaXRhdF92YXJzL2FyaV9haHIuZ3JkIikgJVQ+JQogIHBsb3QKYGBgCgojIyMgTG9nIHZlcnRpY2ljYWwgZGlzdGFuY2UgYWxsIHdldGxhbmRzCmBgYHtyIGx2ZGF3fQpsdmRhdyA8LSByYXN0ZXIoeCA9ICJkYXRhL2dyaWRzL0Vudl9jb3ZhcmlhdGVzX25vQ2xpbWF0ZV9WaWNHcmlkOTQvbG9nX3ZlcnRpY2FsX2Rpc3RhbmNlX2FsbF93ZXRsYW5kc19zZXB0MjAxMiIpICU+JQogIHByb2plY3RSYXN0ZXIodG8gPSBjaF9tYXNrKSAlPiUKICBtYXNrKG1hc2sgPSBjaF9tYXNrLCBmaWxlbmFtZSA9ICJvdXRwdXQvaGFiaXRhdF92YXJzL2FyaV9sdmRhdy5ncmQiKSAlVD4lCiAgcGxvdApgYGAKIyMjIExvZyB2ZXJ0aWNhbCBkaXN0YW5jZSBtYWpvciBzdHJlYW1zCmBgYHtyIGx2ZG1hfQpsdmRtYSA8LSByYXN0ZXIoeCA9ICJkYXRhL2dyaWRzL0Vudl9jb3ZhcmlhdGVzX25vQ2xpbWF0ZV9WaWNHcmlkOTQvbG9nX3ZlcnRpY2FsX2Rpc3RhbmNlX21ham9yX3N0cmVhbXNfc2VwdDIwMTIiKSAlPiUKICBwcm9qZWN0UmFzdGVyKHRvID0gY2hfbWFzaykgJT4lCiAgbWFzayhtYXNrID0gY2hfbWFzaywgZmlsZW5hbWUgPSAib3V0cHV0L2hhYml0YXRfdmFycy9hcmlfbHZkbWEuZ3JkIikgJVQ+JQogIHBsb3QKYGBgCiMjIyBMb2cgdmVydGljYWwgZGlzdGFuY2UgbWlub3Igc3RyZWFtcwpgYGB7ciBsdmRtaX0KbHZkbWkgPC0gcmFzdGVyKHggPSAiZGF0YS9ncmlkcy9FbnZfY292YXJpYXRlc19ub0NsaW1hdGVfVmljR3JpZDk0L2xvZ192ZXJ0aWNhbF9kaXN0YW5jZV9taW5vcl9zdHJlYW1zX3NlcHQyMDEyIikgJT4lCiAgcHJvamVjdFJhc3Rlcih0byA9IGNoX21hc2spICU+JQogIG1hc2sobWFzayA9IGNoX21hc2ssIGZpbGVuYW1lID0gIm91dHB1dC9oYWJpdGF0X3ZhcnMvYXJpX2x2ZG1pLmdyZCIpICVUPiUKICBwbG90CmBgYAojIyMgTG9nIHZlcnRpY2FsIGRpc3RhbmNlIHNhbGluZSB3ZXRsYW5kcwpgYGB7ciBsdmRzd30KbHZkc3cgPC0gcmFzdGVyKHggPSAiZGF0YS9ncmlkcy9FbnZfY292YXJpYXRlc19ub0NsaW1hdGVfVmljR3JpZDk0L2xvZ192ZXJ0aWNhbF9kaXN0YW5jZV9zYWxpbmVfd2V0bGFuZHNfc2VwdDIwMTIiKSAlPiUKICBwcm9qZWN0UmFzdGVyKHRvID0gY2hfbWFzaykgJT4lCiAgbWFzayhtYXNrID0gY2hfbWFzaywgZmlsZW5hbWUgPSAib3V0cHV0L2hhYml0YXRfdmFycy9hcmlfbHZkc3cuZ3JkIikgJVQ+JQogIHBsb3QKYGBgCiMjIyBSZWxhdGl2ZSBhbm51YWwgaW5zb2xhdGlvbgpgYGB7ciByYWl9CnJhaSA8LSByYXN0ZXIoeCA9ICJkYXRhL2dyaWRzL0Vudl9jb3ZhcmlhdGVzX25vQ2xpbWF0ZV9WaWNHcmlkOTQvcmVsYXRpdmVfYW5udWFsX2luc29sYXRpb25fc2VwdDIwMTIiKSAlPiUKICBwcm9qZWN0UmFzdGVyKHRvID0gY2hfbWFzaykgJT4lCiAgbWFzayhtYXNrID0gY2hfbWFzaywgZmlsZW5hbWUgPSAib3V0cHV0L2hhYml0YXRfdmFycy9hcmlfcmFpLmdyZCIpICVUPiUKICBwbG90CmBgYAojIyMgVGhvcml1bQpgYGB7ciB0aG99CnRobyA8LSByYXN0ZXIoeCA9ICJkYXRhL2dyaWRzL0Vudl9jb3ZhcmlhdGVzX25vQ2xpbWF0ZV9WaWNHcmlkOTQvc2VwdDIwMTR0aG9yaXVtIikgJT4lCiAgcHJvamVjdFJhc3Rlcih0byA9IGNoX21hc2spICU+JQogIG1hc2sobWFzayA9IGNoX21hc2ssIGZpbGVuYW1lID0gIm91dHB1dC9oYWJpdGF0X3ZhcnMvYXJpX3Roby5ncmQiKSAlVD4lCiAgcGxvdApgYGAKCiMjIyBWaXNpYmxlIHNreSBpbmRleApgYGB7ciB2c2t5fQp2c2t5IDwtIHJhc3Rlcih4ID0gImRhdGEvZ3JpZHMvRW52X2NvdmFyaWF0ZXNfbm9DbGltYXRlX1ZpY0dyaWQ5NC92aXNpYmxlX3NreV9zZXB0MjAxMiIpICU+JQogIHByb2plY3RSYXN0ZXIodG8gPSBjaF9tYXNrKSAlPiUKICBtYXNrKG1hc2sgPSBjaF9tYXNrLCBmaWxlbmFtZSA9ICJvdXRwdXQvaGFiaXRhdF92YXJzL2FyaV92c2t5LmdyZCIpICVUPiUKICBwbG90CmBgYAoKIyMjIFRvcG9ncmFwaGljIHdldG5lc3MgaW5kZXgKYGBge3IgdHdpfQp0d2kgPC0gcmFzdGVyKHggPSAiZGF0YS9ncmlkcy9FbnZfY292YXJpYXRlc19ub0NsaW1hdGVfVmljR3JpZDk0L3dldG5lc3NfaW5kZXhfdG9wb2Nyb3Bfc2VwdDIwMTIiKSAlPiUKICBwcm9qZWN0UmFzdGVyKHRvID0gY2hfbWFzaykgJT4lCiAgbWFzayhtYXNrID0gY2hfbWFzaywgZmlsZW5hbWUgPSAib3V0cHV0L2hhYml0YXRfdmFycy9hcmlfdHdpLmdyZCIpICVUPiUKICBwbG90CmBgYAoKIyMjIFdpbmQgZXhwb3NpdGlvbgoqKlByb2JsZW0gd2l0aCBsYXllcioqCmBgYHtyIHdpbmV4fQojIHdpbmV4IDwtIHJhc3Rlcih4ID0gImRhdGEvZ3JpZHMvRW52X2NvdmFyaWF0ZXNfbm9DbGltYXRlX1ZpY0dyaWQ5NC93aW5kX2V4cG9zaXRpb24yMDE1IikgJT4lCiAgIyBwcm9qZWN0UmFzdGVyKHRvID0gY2hfbWFzaykgJT4lCiAgIyBtYXNrKG1hc2sgPSBjaF9tYXNrLCBmaWxlbmFtZSA9ICJvdXRwdXQvaGFiaXRhdF92YXJzL2FyaV93aW5leC5ncmQiKSAlVD4lCiAgIyBwbG90CmBgYAoKIyMjIEFSSSB2YXJpYWJsZXMgc3RhY2sKCiMjIyMgSW5pdGlhbCB2YXJpYWJsZXMKYGBge3IgYXJpX2l2fQphcmlfaXYgPC0gc3RhY2sobHZkYXcsIGx2ZG1hLCBsdmRtaSwgbHZkc3cpCgpuYW1lcyhhcmlfaXYpIDwtIGMoImx2ZGF3IiwgImx2ZG1hIiwgImx2ZG1pIiwgImx2ZHN3IikKYGBgCgojIyMjIEZ1dHVyZSB2YXJpYWJsZXMgClJlcGVhdGVzIGludG8gbGlzdCBmb3IgZWFjaCB5ZWFyCmBgYHtyIGFyaV92fQphcmlfdiA8LSB2ZWN0b3IoImxpc3QiLCBudGltZXN0ZXBzICsgMSkKCmZvcihpIGluIDE6KG50aW1lc3RlcHMrMSkpewogIGFyaV92W1tpXV0gPC0gYXJpX2l2Cn0KYGBgCgoKCiMjIENsaW1hY3RpYyBkYXRhCnBjIH4gcGVyY2VudGFnZSBjaGFuZ2UKYWMgfiBhYnNvbHV0ZSBjaGFuZ2UKCnRtYXggfiBtYXggdGVtcGVyYXR1cmUKdG1pbiB+IG1pbmltdW0gdGVtcGVyYXR1cmUKcHJlYyB+IHByZWNpcGl0YXRpb24KZXZ0ciB+IGV2YXBvdHJhbnNwaXJhdGlvbgoKMDEgfiBKYW51YXJ5CjA3IH4gSnVseQoKNC41IH4gcmNwIDQuNQo4LjUgfiByY3AgOC41CgoKIyMjIEN1cnJlbnQgY2xpbWF0ZQpGcm9tIFdvcmxkQ2xpbQoKIyMjIyBQcmVjaXBpdGF0aW9uIGluIEphbnVhcnkKYGBge3IgcHJlYzAxfQpwcmVjMDEgPC0gcmFzdGVyKCJkYXRhL2dyaWRzL3djMi4wXzMwc19wcmVjXzAxLnRpZiIpICU+JQogIHByb2plY3RSYXN0ZXIodG8gPSBjaF9tYXNrKSAlPiUKICBtYXNrKG1hc2sgPSBjaF9tYXNrLCBmaWxlbmFtZSA9ICJvdXRwdXQvY2xpbV92YXJzL3ByZWMwMS5ncmQiKQoKbmFtZXMocHJlYzAxKSA8LSAicHJlYzAxIgoKcGxvdChwcmVjMDEpCmBgYAoKIyMjIyBQcmVjaXBpdGF0aW9uIGluIEp1bHkKYGBge3IgcHJlYzA3fQpwcmVjMDcgPC0gcmFzdGVyKCJkYXRhL2dyaWRzL3djMi4wXzMwc19wcmVjXzA3LnRpZiIpICU+JQogIHByb2plY3RSYXN0ZXIodG8gPSBjaF9tYXNrKSAlPiUKICBtYXNrKG1hc2sgPSBjaF9tYXNrLCBmaWxlbmFtZSA9ICJvdXRwdXQvY2xpbV92YXJzL3ByZWMwNy5ncmQiKQoKbmFtZXMocHJlYzA3KSA8LSAicHJlYzA3IgoKcGxvdChwcmVjMDcpCmBgYAoKIyMjIyBNYXggdGVtcGVyYXR1cmUgaW4gSmFudWFyeQpgYGB7ciB0bWF4MDF9CnRtYXgwMSA8LSByYXN0ZXIoImRhdGEvZ3JpZHMvd2MyLjBfMzBzX3RtYXhfMDEudGlmIikgJT4lCiAgcHJvamVjdFJhc3Rlcih0byA9IGNoX21hc2spICU+JQogIG1hc2sobWFzayA9IGNoX21hc2ssIGZpbGVuYW1lID0gIm91dHB1dC9jbGltX3ZhcnMvdG1heDAxLmdyZCIpCgpuYW1lcyh0bWF4MDEpIDwtICJ0bWF4MDEiCgpwbG90KHRtYXgwMSkKYGBgCgojIyMjIE1pbmltdW0gdGVtcGVyYXR1cmUgaW4gSnVseQpgYGB7ciB0bWluMDd9CnRtaW4wNyA8LSByYXN0ZXIoImRhdGEvZ3JpZHMvd2MyLjBfMzBzX3RtaW5fMDcudGlmIikgJT4lCiAgcHJvamVjdFJhc3Rlcih0byA9IGNoX21hc2spICU+JQogIG1hc2sobWFzayA9IGNoX21hc2ssIGZpbGVuYW1lID0gIm91dHB1dC9jbGltX3ZhcnMvdG1pbjA3LmdyZCIpCgpuYW1lcyh0bWluMDcpIDwtICJ0bWluMDciCgpwbG90KHRtaW4wNykKYGBgCgoKIyMjIEZ1dHVyZSBjbGltYXRlCkRhdGEgZnJvbSBbQ2xpbWF0ZSBDaGFuZ2UgaW4gQXVzdHJhbGlhXShodHRwczovL3d3dy5jbGltYXRlY2hhbmdlaW5hdXN0cmFsaWEuZ292LmF1L2VuLykKCiMjIyMgQ2hhbmdlIGRhdGEKKlRoZXJlIHNob3VsZCBiZSBuZXcgZGF0YSB0byByZXBsYWNlIHRoaXMgKgojIyMjIyBBYnNvbHV0ZSBjaGFuZ2UgaW4gdGVtcGVyYXR1cmUKR2V0IHJhdyBkYXRhCmBgYHtyIHJhdyB0ZW1wIGFjfQojYWJzb2x1dGUgY2hhbmdlIGluIHRlbXAKcmF3X3RtYXgwMV80LjVfYWMgPC0gcmVhZC5tdWx0aS5saW5lLmhlYWRlcihmaWxlID0gImh0dHA6Ly9ucm0tZXJkZGFwLm5jaS5vcmcuYXUvZXJkZGFwL2dyaWRkYXAvdGFzbWF4X0Ftb25fQ1NJUk8tTWszLTYtMF9yY3A0NV9yMWkxcDFfYWJzLWNoYW5nZS13cnQtc2Vhc2F2Zy1jbGltX25hdGl2ZS5jc3Y/dGFzbWF4X2phbnVhcnlbKDIwMjUtMDEtMDFUMTI6MDA6MDBaKToxOigyMDkwLTAxLTAxVDEyOjAwOjAwWildWygtNDAuMTAyOTc3NzUpOjE6KC0zMi42NDE5OTQ0OCldWygxNDAuNjI1KToxOigxNTApXSIpCgpyYXdfdG1heDAxXzguNV9hYyA8LSByZWFkLm11bHRpLmxpbmUuaGVhZGVyKGZpbGUgPSAiaHR0cDovL25ybS1lcmRkYXAubmNpLm9yZy5hdS9lcmRkYXAvZ3JpZGRhcC90YXNtYXhfQW1vbl9DU0lSTy1NazMtNi0wX3JjcDg1X3IxaTFwMV9hYnMtY2hhbmdlLXdydC1zZWFzYXZnLWNsaW1fbmF0aXZlLmNzdj90YXNtYXhfamFudWFyeVsoMjAyNS0wMS0wMVQxMjowMDowMFopOjE6KDIwOTAtMDEtMDFUMTI6MDA6MDBaKV1bKC00MC4xMDI5Nzc3NSk6MTooLTMyLjY0MTk5NDQ4KV1bKDE0MC42MjUpOjE6KDE1MCldIikKCnJhd190bWluMDdfNC41X2FjIDwtIHJlYWQubXVsdGkubGluZS5oZWFkZXIoZmlsZSA9ICJodHRwOi8vbnJtLWVyZGRhcC5uY2kub3JnLmF1L2VyZGRhcC9ncmlkZGFwL3Rhc21pbl9BbW9uX0NTSVJPLU1rMy02LTBfcmNwNDVfcjFpMXAxX2Ficy1jaGFuZ2Utd3J0LXNlYXNhdmctY2xpbV9uYXRpdmUuY3N2P3Rhc21pbl9qdWx5WygyMDI1LTAxLTAxVDEyOjAwOjAwWik6MTooMjA5MC0wMS0wMVQxMjowMDowMFopXVsoLTQwLjEwMjk3Nzc1KToxOigtMzIuNjQxOTk0NDgpXVsoMTQwLjYyNSk6MTooMTUwKV0iKSAKCnJhd190bWluMDdfOC41X2FjIDwtIHJlYWQubXVsdGkubGluZS5oZWFkZXIoZmlsZSA9ICJodHRwOi8vbnJtLWVyZGRhcC5uY2kub3JnLmF1L2VyZGRhcC9ncmlkZGFwL3Rhc21pbl9BbW9uX0NTSVJPLU1rMy02LTBfcmNwODVfcjFpMXAxX2Ficy1jaGFuZ2Utd3J0LXNlYXNhdmctY2xpbV9uYXRpdmUuY3N2P3Rhc21pbl9qdWx5WygyMDI1LTAxLTAxVDEyOjAwOjAwWik6MTooMjA5MC0wMS0wMVQxMjowMDowMFopXVsoLTQwLjEwMjk3Nzc1KToxOigtMzIuNjQxOTk0NDgpXVsoMTQwLjYyNSk6MTooMTUwKV0iKQpgYGAKWWVhcnMgZGF0YSBhdmFpbGFibGUKYGBge3IgbiB0ZW1wIGFjfQpuX3RtYXgwMV80LjUgPC0gYXMubnVtZXJpYyhzdWIoIi0uKiIsICIiLCB1bmlxdWUocmF3X3RtYXgwMV80LjVfYWMkdGltZSkpKQpuX3RtYXgwMV84LjUgPC0gYXMubnVtZXJpYyhzdWIoIi0uKiIsICIiLCB1bmlxdWUocmF3X3RtYXgwMV84LjVfYWMkdGltZSkpKQpuX3RtaW4wN180LjUgPC0gYXMubnVtZXJpYyhzdWIoIi0uKiIsICIiLCB1bmlxdWUocmF3X3RtaW4wN180LjVfYWMkdGltZSkpKQpuX3RtaW4wN184LjUgPC0gYXMubnVtZXJpYyhzdWIoIi0uKiIsICIiLCB1bmlxdWUocmF3X3RtaW4wN184LjVfYWMkdGltZSkpKQpgYGAKClJlcHJvamVjdGVkIGxheWVycwpgYGB7ciByYXN0ZXJzIHRlbXAgYWN9CnRtYXgwMV80LjVfYWMgPC0gcmFzY2MocmF3X3RtYXgwMV80LjVfYWMsIG5ldy5wcm9qLmxheWVyID0gY2hfbWFzaywgZmlsZW5hbWUgPSAib3V0cHV0L2NsaW1fdmFycy90bWF4MDFfNC41X2FjLmdyZCIpCnRtYXgwMV84LjVfYWMgPC0gcmFzY2MocmF3X3RtYXgwMV84LjVfYWMsIG5ldy5wcm9qLmxheWVyID0gY2hfbWFzaywgZmlsZW5hbWUgPSAib3V0cHV0L2NsaW1fdmFycy90bWF4MDFfOC41X2FjLmdyZCIpCnRtaW4wN180LjVfYWMgPC0gcmFzY2MocmF3X3RtaW4wN180LjVfYWMsIG5ldy5wcm9qLmxheWVyID0gY2hfbWFzaywgZmlsZW5hbWUgPSAib3V0cHV0L2NsaW1fdmFycy90bWluMDdfNC41X2FjLmdyZCIpCnRtaW4wN184LjVfYWMgPC0gcmFzY2MocmF3X3RtaW4wN184LjVfYWMsIG5ldy5wcm9qLmxheWVyID0gY2hfbWFzaywgZmlsZW5hbWUgPSAib3V0cHV0L2NsaW1fdmFycy90bWluMDdfOC41X2FjLmdyZCIpCmBgYAoKIyMjIyMgUGVyY2VudGFnZSBjaGFuZ2UgaW4gcHJlY2lwaXRhdGlvbgpHZXQgcmF3IGRhdGEKYGBge3IgcmF3IHByZWMgcGN9CnJhd19wcmVjMDFfNC41X3BjIDwtIHJlYWQubXVsdGkubGluZS5oZWFkZXIoZmlsZSA9ICJodHRwOi8vbnJtLWVyZGRhcC5uY2kub3JnLmF1L2VyZGRhcC9ncmlkZGFwL3ByX0Ftb25fQ1NJUk8tTWszLTYtMF9yY3A0NV9yMWkxcDFfcGVyYy1jaGFuZ2Utd3J0LXNlYXNzdW0tY2xpbV9uYXRpdmUuY3N2P3ByX2phbnVhcnlbKDIwMjUtMDEtMDFUMTI6MDA6MDBaKToxOigyMDkwLTAxLTAxVDEyOjAwOjAwWildWygtNDAuMTAyOTc3NzUpOjE6KC0zMi42NDE5OTQ0OCldWygxNDAuNjI1KToxOigxNTApXSIpCgpyYXdfcHJlYzAxXzguNV9wYyA8LSByZWFkLm11bHRpLmxpbmUuaGVhZGVyKGZpbGUgPSAiaHR0cDovL25ybS1lcmRkYXAubmNpLm9yZy5hdS9lcmRkYXAvZ3JpZGRhcC9wcl9BbW9uX0NTSVJPLU1rMy02LTBfcmNwODVfcjFpMXAxX3BlcmMtY2hhbmdlLXdydC1zZWFzc3VtLWNsaW1fbmF0aXZlLmNzdj9wcl9qYW51YXJ5WygyMDI1LTAxLTAxVDEyOjAwOjAwWik6MTooMjA5MC0wMS0wMVQxMjowMDowMFopXVsoLTQwLjEwMjk3Nzc1KToxOigtMzIuNjQxOTk0NDgpXVsoMTQwLjYyNSk6MTooMTUwKV0iKQoKcmF3X3ByZWMwN180LjVfcGMgPC0gcmVhZC5tdWx0aS5saW5lLmhlYWRlcihmaWxlID0gImh0dHA6Ly9ucm0tZXJkZGFwLm5jaS5vcmcuYXUvZXJkZGFwL2dyaWRkYXAvcHJfQW1vbl9DU0lSTy1NazMtNi0wX3JjcDQ1X3IxaTFwMV9wZXJjLWNoYW5nZS13cnQtc2Vhc3N1bS1jbGltX25hdGl2ZS5jc3Y/cHJfanVseVsoMjAyNS0wMS0wMVQxMjowMDowMFopOjE6KDIwOTAtMDEtMDFUMTI6MDA6MDBaKV1bKC00MC4xMDI5Nzc3NSk6MTooLTMyLjY0MTk5NDQ4KV1bKDE0MC42MjUpOjE6KDE1MCldIikKCnJhd19wcmVjMDdfOC41X3BjIDwtIHJlYWQubXVsdGkubGluZS5oZWFkZXIoZmlsZSA9ICJodHRwOi8vbnJtLWVyZGRhcC5uY2kub3JnLmF1L2VyZGRhcC9ncmlkZGFwL3ByX0Ftb25fQ1NJUk8tTWszLTYtMF9yY3A4NV9yMWkxcDFfcGVyYy1jaGFuZ2Utd3J0LXNlYXNzdW0tY2xpbV9uYXRpdmUuY3N2P3ByX2p1bHlbKDIwMjUtMDEtMDFUMTI6MDA6MDBaKToxOigyMDkwLTAxLTAxVDEyOjAwOjAwWildWygtNDAuMTAyOTc3NzUpOjE6KC0zMi42NDE5OTQ0OCldWygxNDAuNjI1KToxOigxNTApXSIpCmBgYAoKWWVhcnMgZGF0YSBhdmFpbGFibGUKYGBge3IgbiBwcmVjIHBjfQpuX3ByZWMwMV80LjUgPC0gYXMubnVtZXJpYyhzdWIoIi0uKiIsICIiLCB1bmlxdWUocmF3X3ByZWMwMV80LjVfcGMkdGltZSkpKQpuX3ByZWMwMV84LjUgPC0gYXMubnVtZXJpYyhzdWIoIi0uKiIsICIiLCB1bmlxdWUocmF3X3ByZWMwMV80LjVfcGMkdGltZSkpKQpuX3ByZWMwN180LjUgPC0gYXMubnVtZXJpYyhzdWIoIi0uKiIsICIiLCB1bmlxdWUocmF3X3ByZWMwN180LjVfcGMkdGltZSkpKQpuX3ByZWMwN184LjUgPC0gYXMubnVtZXJpYyhzdWIoIi0uKiIsICIiLCB1bmlxdWUocmF3X3ByZWMwN180LjVfcGMkdGltZSkpKQpgYGAKClJlcHJvamVjdGVkIGxheWVycwpgYGB7ciByYXN0ZXIgcHJlYyBwY30KcHJlYzAxXzQuNV9wYyA8LSByYXNjYyhyYXdfcHJlYzAxXzQuNV9wYywgbmV3LnByb2oubGF5ZXIgPSBjaF9tYXNrLCBmaWxlbmFtZSA9ICJvdXRwdXQvY2xpbV92YXJzL3ByZWMwMV80LjVfcGMuZ3JkIikKcHJlYzAxXzguNV9wYyA8LSByYXNjYyhyYXdfcHJlYzAxXzguNV9wYywgbmV3LnByb2oubGF5ZXIgPSBjaF9tYXNrLCBmaWxlbmFtZSA9ICJvdXRwdXQvY2xpbV92YXJzL3ByZWMwMV84LjVfcGMuZ3JkIikKcHJlYzA3XzQuNV9wYyA8LSByYXNjYyhyYXdfcHJlYzA3XzQuNV9wYywgbmV3LnByb2oubGF5ZXIgPSBjaF9tYXNrLCBmaWxlbmFtZSA9ICJvdXRwdXQvY2xpbV92YXJzL3ByZWMwN180LjVfcGMuZ3JkIikKcHJlYzA3XzguNV9wYyA8LSByYXNjYyhyYXdfcHJlYzA3XzguNV9wYywgbmV3LnByb2oubGF5ZXIgPSBjaF9tYXNrLCBmaWxlbmFtZSA9ICJvdXRwdXQvY2xpbV92YXJzL3ByZWMwN184LjVfcGMuZ3JkIikKYGBgCgoKCiMjIyMgIEFic29sdXRlIHByZWRpY3RlZCB2YWx1ZXMKCiMjIyMjIFRlbXBlcmF0dXJlCgphZGQgbmV3IGZ1bmN0aW9uIHRoYXQgd3JpdGVzIHRoZXNlIGNsaW1hdGUgbGF5ZXJzIHRvIGZpbGVzLgoKCiMjIyMjIyBKYW4gbWF4IHRlbXBlcmF0dXJlIFJDUCA0LjUKYGBge3IgdG1heDAxXzQuNX0KdG1heDAxXzQuNSA8LSByc3Qub3AoaW5wdXQxID0gdG1heDAxLAogICAgICAgICAgICAgICAgICAgICBpbnB1dDIgPSB0bWF4MDFfNC41X2FjLAogICAgICAgICAgICAgICAgICAgICBwcm9qX21hc2sgPSBjaF9tYXNrLAogICAgICAgICAgICAgICAgICAgICBvcCA9ICJhZGRhYnMiLAogICAgICAgICAgICAgICAgICAgICBmaWxlbmFtZSA9ICJvdXRwdXQvY2xpbV92YXJzL3RtYXgwMV80LjUiLAogICAgICAgICAgICAgICAgICAgICBsYXllcm5hbWVzID0gbl90bWF4MDFfNC41KSAlVD4lCiAgcGxvdApgYGAKCiMjIyMjIyBKYW4gbWF4IHRlbXBlcmF0dXJlIFJDUCA4LjUKYGBge3IgdG1heDAxXzguNX0KdG1heDAxXzguNSA8LSByc3Qub3AoaW5wdXQxID0gdG1heDAxLAogICAgICAgICAgICAgICAgICAgICBpbnB1dDIgPSB0bWF4MDFfOC41X2FjLAogICAgICAgICAgICAgICAgICAgICBwcm9qX21hc2sgPSBjaF9tYXNrLAogICAgICAgICAgICAgICAgICAgICBvcCA9ICJhZGRhYnMiLAogICAgICAgICAgICAgICAgICAgICBmaWxlbmFtZSA9ICJvdXRwdXQvY2xpbV92YXJzL3RtYXgwMV84LjUiLAogICAgICAgICAgICAgICAgICAgICBsYXllcm5hbWVzID0gbl90bWF4MDFfOC41KSAlVD4lCiAgcGxvdApgYGAKIyMjIyMjIEp1bHkgbWluIHRlbXBlcmF0dXJlIFJDUCA0LjUKYGBge3IgdG1pbjA3XzQuNX0KdG1pbjA3XzQuNSA8LSByc3Qub3AoaW5wdXQxID0gdG1pbjA3LAogICAgICAgICAgICAgICAgICAgICBpbnB1dDIgPSB0bWluMDdfNC41X2FjLAogICAgICAgICAgICAgICAgICAgICBwcm9qX21hc2sgPSBjaF9tYXNrLAogICAgICAgICAgICAgICAgICAgICBvcCA9ICJhZGRhYnMiLAogICAgICAgICAgICAgICAgICAgICBmaWxlbmFtZSA9ICJvdXRwdXQvY2xpbV92YXJzL3RtaW4wN180LjUiLAogICAgICAgICAgICAgICAgICAgICBsYXllcm5hbWVzID0gbl90bWluMDdfNC41KSAlVD4lCiAgcGxvdApgYGAKCiMjIyMjIyBKdWx5IG1pbiB0ZW1wZXJhdHVyZSBSQ1AgOC41CmBgYHtyIHRtaW4wN184LjV9CnRtaW4wN184LjUgPC0gcnN0Lm9wKGlucHV0MSA9IHRtaW4wNywKICAgICAgICAgICAgICAgICAgICAgaW5wdXQyID0gdG1pbjA3XzguNV9hYywKICAgICAgICAgICAgICAgICAgICAgcHJval9tYXNrID0gY2hfbWFzaywKICAgICAgICAgICAgICAgICAgICAgb3AgPSAiYWRkYWJzIiwKICAgICAgICAgICAgICAgICAgICAgZmlsZW5hbWUgPSAib3V0cHV0L2NsaW1fdmFycy90bWluMDdfOC41IiwKICAgICAgICAgICAgICAgICAgICAgbGF5ZXJuYW1lcyA9IG5fdG1pbjA3XzguNSkgJVQ+JQogIHBsb3QKYGBgCgojIyMjIyBQcmVjaXBpdGF0aW9uCgojIyMjIyBKYW51YXJ5IHByZWNpcGl0YXRpb24gUkNQIDQuNQpgYGB7ciBwcmVjMDFfNC41fQpwcmVjMDFfNC41IDwtIHJzdC5vcChpbnB1dDEgPSBwcmVjMDEsCiAgICAgICAgICAgICAgICAgICAgIGlucHV0MiA9IHByZWMwMV80LjVfcGMsCiAgICAgICAgICAgICAgICAgICAgIHByb2pfbWFzayA9IGNoX21hc2ssCiAgICAgICAgICAgICAgICAgICAgIG9wID0gImFkZHBlciIsCiAgICAgICAgICAgICAgICAgICAgIGZpbGVuYW1lID0gIm91dHB1dC9jbGltX3ZhcnMvcHJlYzAxXzQuNSIsCiAgICAgICAgICAgICAgICAgICAgIGxheWVybmFtZXMgPSBuX3ByZWMwMV80LjUpICVUPiUKICBwbG90CmBgYAoKIyMjIyMgSmFudWFyeSBwcmVjaXBpdGF0aW9uIFJDUCA4LjUKYGBge3IgcHJlYzAxXzguNX0KcHJlYzAxXzguNSA8LSByc3Qub3AoaW5wdXQxID0gcHJlYzAxLAogICAgICAgICAgICAgICAgICAgICBpbnB1dDIgPSBwcmVjMDFfOC41X3BjLAogICAgICAgICAgICAgICAgICAgICBwcm9qX21hc2sgPSBjaF9tYXNrLAogICAgICAgICAgICAgICAgICAgICBvcCA9ICJhZGRwZXIiLAogICAgICAgICAgICAgICAgICAgICBmaWxlbmFtZSA9ICJvdXRwdXQvY2xpbV92YXJzL3ByZWMwMV84LjUiLAogICAgICAgICAgICAgICAgICAgICBsYXllcm5hbWVzID0gbl9wcmVjMDFfOC41KSAlVD4lCiAgcGxvdApgYGAKCiMjIyMjIEp1bHkgcHJlY2lwaXRhdGlvbiBSQ1AgNC41CmBgYHtyIHByZWMwN180LjV9CnByZWMwN180LjUgPC0gcnN0Lm9wKGlucHV0MSA9IHByZWMwNywKICAgICAgICAgICAgICAgICAgICAgaW5wdXQyID0gcHJlYzA3XzQuNV9wYywKICAgICAgICAgICAgICAgICAgICAgcHJval9tYXNrID0gY2hfbWFzaywKICAgICAgICAgICAgICAgICAgICAgb3AgPSAiYWRkcGVyIiwKICAgICAgICAgICAgICAgICAgICAgZmlsZW5hbWUgPSAib3V0cHV0L2NsaW1fdmFycy9wcmVjMDdfNC41IiwKICAgICAgICAgICAgICAgICAgICAgbGF5ZXJuYW1lcyA9IG5fcHJlYzA3XzQuNSkgJVQ+JQogIHBsb3QKYGBgCgojIyMjIyBKdWx5IHByZWNpcGl0YXRpb24gUkNQIDguNQpgYGB7ciBwcmVjMDdfOC41fQpwcmVjMDdfOC41IDwtIHJzdC5vcChpbnB1dDEgPSBwcmVjMDcsCiAgICAgICAgICAgICAgICAgICAgIGlucHV0MiA9IHByZWMwN184LjVfcGMsCiAgICAgICAgICAgICAgICAgICAgIHByb2pfbWFzayA9IGNoX21hc2ssCiAgICAgICAgICAgICAgICAgICAgIG9wID0gImFkZHBlciIsCiAgICAgICAgICAgICAgICAgICAgIGZpbGVuYW1lID0gIm91dHB1dC9jbGltX3ZhcnMvcHJlYzA3XzguNSIsCiAgICAgICAgICAgICAgICAgICAgIGxheWVybmFtZXMgPSBuX3ByZWMwN184LjUpICVUPiUKICBwbG90CmBgYAoKIyMjIyBJbnRlcnBsb2F0ZSBwcmVkaWN0aW9uIGRhdGEKKipDdXJyZW50bHkganVzdCByZXBlYXRzIHByZWRpY3Rpb25zIGZvciBuZWFyZXN0IHllYXIsIG5lZWQgdXBkYXRpbmcgdG8gd2VpZ2h0IHByZWRpY3Rpb25zIHdpdGhpbiAxMCB5ZWFycywgY2YgZGF0YSBmcm9tIENTSVJPKioKYGBge3J9CnRtYXgwMV80LjVfaW50IDwtIGludGVycG9sYXRlLmNsaW1kYXQodG1heDAxLCB0bWF4MDFfNC41LCBueSA9IG50aW1lc3RlcHMsIG5mID0gbl90bWF4MDFfNC41LCBuMCA9IDIwMTksIHZhcm5hbWUgPSAidG1heDAxIikKdG1heDAxXzguNV9pbnQgPC0gaW50ZXJwb2xhdGUuY2xpbWRhdCh0bWF4MDEsIHRtYXgwMV84LjUsIG55ID0gNTAsIG5mID0gbl90bWF4MDFfOC41LCBuMCA9IDIwMTksIHZhcm5hbWUgPSAidG1heDAxIikKdG1pbjA3XzQuNV9pbnQgPC0gaW50ZXJwb2xhdGUuY2xpbWRhdCh0bWluMDcsIHRtaW4wN180LjUsIG55ID0gNTAsIG5mID0gbl90bWluMDdfNC41LCBuMCA9IDIwMTksIHZhcm5hbWUgPSAidG1pbjA3IikKdG1pbjA3XzguNV9pbnQgPC0gaW50ZXJwb2xhdGUuY2xpbWRhdCh0bWluMDcsIHRtaW4wN184LjUsIG55ID0gNTAsIG5mID0gbl90bWluMDdfOC41LCBuMCA9IDIwMTksIHZhcm5hbWUgPSAidG1pbjA3IikKCnByZWMwMV80LjVfaW50IDwtIGludGVycG9sYXRlLmNsaW1kYXQocHJlYzAxLCBwcmVjMDFfNC41LCBueSA9IDUwLCBuZiA9IG5fcHJlYzAxXzQuNSwgbjAgPSAyMDE5LCB2YXJuYW1lID0gInByZWMwMSIpCnByZWMwMV84LjVfaW50IDwtIGludGVycG9sYXRlLmNsaW1kYXQocHJlYzAxLCBwcmVjMDFfOC41LCBueSA9IDUwLCBuZiA9IG5fcHJlYzAxXzguNSwgbjAgPSAyMDE5LCB2YXJuYW1lID0gInByZWMwMSIpCnByZWMwN180LjVfaW50IDwtIGludGVycG9sYXRlLmNsaW1kYXQocHJlYzA3LCBwcmVjMDdfNC41LCBueSA9IDUwLCBuZiA9IG5fcHJlYzA3XzQuNSwgbjAgPSAyMDE5LCB2YXJuYW1lID0gInByZWMwNyIpCnByZWMwN184LjVfaW50IDwtIGludGVycG9sYXRlLmNsaW1kYXQocHJlYzA3LCBwcmVjMDdfOC41LCBueSA9IDUwLCBuZiA9IG5fcHJlYzA3XzguNSwgbjAgPSAyMDE5LCB2YXJuYW1lID0gInByZWMwNyIpCmBgYAoKIyMjIENsaW1hdGUgdmFyaWFibGUgc2V0cwoKIyMjIyBJbml0aWFsIGNsaW1hdGUgdmFyaWFibGVzCmBgYHtyIGNsaW0gaXZ9CmNsaW1faXYgPC0gc3RhY2socHJlYzAxLCBwcmVjMDcsIHRtYXgwMSwgdG1pbjA3KQpgYGAKCiMjIyMgRnV0dXJlIGNsaW1hdGUgdmFyaWFibGVzCmBgYHtyIGNsaW1fZnZ9CmNsaW1fZnZfY2MwIDwtIHZlY3RvcigibGlzdCIsIDUwKQpmb3IoaSBpbiAxOjUwKXsKICBjbGltX2Z2X2NjMFtbaV1dIDwtIGNsaW1faXYKfQoKCmNsaW1fZnZfNC41IDwtIG1hcHBseShwcmVjMDFfNC41X2ludCwgcHJlYzA3XzQuNV9pbnQsIHRtYXgwMV80LjVfaW50LCB0bWluMDdfNC41X2ludCwgRlVOID0gc3RhY2spCmNsaW1fZnZfOC41IDwtIG1hcHBseShwcmVjMDFfOC41X2ludCwgcHJlYzA3XzguNV9pbnQsIHRtYXgwMV84LjVfaW50LCB0bWluMDdfOC41X2ludCwgRlVOID0gc3RhY2spCmBgYAoKYGBge3J9CnNhdmUuaW1hZ2UoZmlsZSA9ICJvdXRwdXQvaW5wdXRfdmFyaWFibGVzLlJEYXRhIikKYGBgCgoKIyMgRGlzdHJpYnV0aW9uIG1vZGVsIHZhcmlhYmxlcwoKIyMjIFNwZWNpZXMgTEFORElTIHZhcmlhYmxlcwoKIyMjIyBHRyBMQU5ESVMgdmFycwpgYGB7ciBnZ19sdn0KZ2dsdiA8LSBjKCJnZ2YiLCAiZ2dkIiwgImhidF8xayIpCmBgYAoKCiMjIyMgTEIgTEFORElTIHZhcnMKYGBge3J9CmxibHYgPC0gYygibGJtIiwgImhidF8zaCIpCmBgYAoKCiMjIyBTY2VuYXJpbyAxCgojIyMjIEdyZWF0ZXIgR2xpZGVyCgojIyMjIyBTY2VuYXJpbyAxIGluaXRpYWwgdmFyaWFibGVzCmBgYHtyIHMxX2l2X2dnfQpzMV9pdl9nZyA8LSBzdGFjayhzMV92YXJzX2xhbmRpc19pbml0W1tjKGdnbHYpXV0sIGNsaW1faXYpCgpzYXZlKHMxX2l2X2dnLCBmaWxlID0gIm91dHB1dC9oYWJpdGF0X3ZhcnMvczFfaXZfZ2ciKQpgYGAKCiMjIyMjIFNjZW5haW8gMSBtb2RlbCBkYXRhCmBgYHtyfQpzMV9tZF9nZyA8LSBzMV9pdl9nZyAlPiUKICByYXN0ZXI6OmV4dHJhY3QoeSA9IHN0X2Nvb3JkaW5hdGVzKGdnX3BhX2NoKSkgJT4lCiAgY2JpbmQoIlBBIiA9IGdnX3BhX2NoJFBBLCAuKSAlPiUKICBhcy5kYXRhLmZyYW1lICU+JQogIG5hLm9taXQgCgpzMV9tZF9nZwoKc2F2ZShzMV9tZF9nZywgZmlsZSA9ICJvdXRwdXQvaGFiaXRhdF92YXJzL3MxX21kX2dnIikKYGBgCgoKIyMjIyMgU2NlbmFyaW8gMSBmdXR1cmUgdmFyaWFibGVzCmBgYHtyIHMxX2Z2X2dnfQpzMV9mdl9nZyA8LSBzMV92YXJzX2xhbmRpc19mdXQgJT4lCiAgc2FwcGx5KCJbWyIsIGdnbHYpICU+JQogIG1hcHBseShjbGltX2Z2XzQuNSwgRlVOID0gc3RhY2spCgpzYXZlKHMxX2Z2X2dnLCBmaWxlID0gIm91dHB1dC9oYWJpdGF0X3ZhcnMvczFfZnZfZ2ciKQpgYGAKCgojIyMjIExlYWRiZWF0ZXIncyBQb3NzdW0KCiMjIyMjIFNjZW5hcmlvIDEgaW5pdGlhbCB2YXJpYWJsZXMKYGBge3IgczFfaXZfbGJ9CnMxX2l2X2xiIDwtIHN0YWNrKHMxX3ZhcnNfbGFuZGlzX2luaXRbW2MobGJsdildXSwgY2xpbV9pdikKCnNhdmUoczFfaXZfbGIsIGZpbGUgPSAib3V0cHV0L2hhYml0YXRfdmFycy9zMV9pdl9sYiIpCmBgYAoKIyMjIyMgU2NlbmFpbyAxIG1vZGVsIGRhdGEKYGBge3J9CnMxX21kX2xiIDwtIHMxX2l2X2xiICU+JQogIHJhc3Rlcjo6ZXh0cmFjdCh5ID0gc3RfY29vcmRpbmF0ZXMobGJfcGFfY2gpKSAlPiUKICBjYmluZCgiUEEiID0gbGJfcGFfY2gkUEEsIC4pICU+JQogIGFzLmRhdGEuZnJhbWUgJT4lCiAgbmEub21pdCAKCnMxX21kX2xiCgpzYXZlKHMxX21kX2xiLCBmaWxlID0gIm91dHB1dC9oYWJpdGF0X3ZhcnMvczFfbWRfbGIiKQpgYGAKCgojIyMjIyBTY2VuYXJpbyAxIGZ1dHVyZSB2YXJpYWJsZXMKYGBge3IgczFfZnZfbGJ9CnMxX2Z2X2xiIDwtIHMxX3ZhcnNfbGFuZGlzX2Z1dCAlPiUKICBzYXBwbHkoIltbIiwgbGJsdikgJT4lCiAgbWFwcGx5KGNsaW1fZnZfNC41LCBGVU4gPSBzdGFjaykKCnNhdmUoczFfZnZfbGIsIGZpbGUgPSAib3V0cHV0L2hhYml0YXRfdmFycy9zMV9mdl9sYiIpCmBgYAoKIyMjIFNjZW5hcmlvIDIKKiphd2FpdGluZyB1cGRhdGVkIGNsaW1hdGUgdmFyaWFibGVzKioKCgojIyMgU2NlbmFyaW8gMwoKIyMjIyBHcmVhdGVyIEdsaWRlcgoKIyMjIyMgU2NlbmFyaW8gMyBpbml0aWFsIHZhcmlhYmxlcwpgYGB7ciBzM19pdl9nZ30KczNfaXZfZ2cgPC0gc3RhY2soczNfdmFyc19sYW5kaXNfaW5pdFtbYyhnZ2x2KV1dLCBjbGltX2l2KQoKc2F2ZShzM19pdl9nZywgZmlsZSA9ICJvdXRwdXQvaGFiaXRhdF92YXJzL3MzX2l2X2dnIikKYGBgCgojIyMjIyBTY2VuYWlvIDMgbW9kZWwgZGF0YQpgYGB7cn0KczNfbWRfZ2cgPC0gczNfaXZfZ2cgJT4lCiAgcmFzdGVyOjpleHRyYWN0KHkgPSBzdF9jb29yZGluYXRlcyhnZ19wYV9jaCkpICU+JQogIGNiaW5kKCJQQSIgPSBnZ19wYV9jaCRQQSwgLikgJT4lCiAgYXMuZGF0YS5mcmFtZSAlPiUKICBuYS5vbWl0IAoKczNfbWRfZ2cKCnNhdmUoczNfbWRfZ2csIGZpbGUgPSAib3V0cHV0L2hhYml0YXRfdmFycy9zM19tZF9nZyIpCmBgYAoKCiMjIyMjIFNjZW5hcmlvIDMgZnV0dXJlIHZhcmlhYmxlcwpgYGB7ciBzM19mdl9nZ30KczNfZnZfZ2cgPC0gczNfdmFyc19sYW5kaXNfZnV0ICU+JQogIHNhcHBseSgiW1siLCBnZ2x2KSAlPiUKICBtYXBwbHkoY2xpbV9mdl9jYzAsIEZVTiA9IHN0YWNrKQoKc2F2ZShzM19mdl9nZywgZmlsZSA9ICJvdXRwdXQvaGFiaXRhdF92YXJzL3MzX2Z2X2dnIikKYGBgCgoKIyMjIyBMZWFkYmVhdGVyJ3MgUG9zc3VtCgojIyMjIyBTY2VuYXJpbyAzIGluaXRpYWwgdmFyaWFibGVzCmBgYHtyIHMzX2l2X2xifQpzM19pdl9sYiA8LSBzdGFjayhzM192YXJzX2xhbmRpc19pbml0W1tjKGxibHYpXV0sIGNsaW1faXYpCgpzYXZlKHMzX2l2X2xiLCBmaWxlID0gIm91dHB1dC9oYWJpdGF0X3ZhcnMvczNfaXZfbGIiKQpgYGAKCiMjIyMjIFNjZW5haW8gMyBtb2RlbCBkYXRhCmBgYHtyfQpzM19tZF9sYiA8LSBzM19pdl9sYiAlPiUKICByYXN0ZXI6OmV4dHJhY3QoeSA9IHN0X2Nvb3JkaW5hdGVzKGxiX3BhX2NoKSkgJT4lCiAgY2JpbmQoIlBBIiA9IGxiX3BhX2NoJFBBLCAuKSAlPiUKICBhcy5kYXRhLmZyYW1lICU+JQogIG5hLm9taXQgCgpzM19tZF9sYgoKc2F2ZShzM19tZF9sYiwgZmlsZSA9ICJvdXRwdXQvaGFiaXRhdF92YXJzL3MzX21kX2xiIikKYGBgCgoKIyMjIyMgU2NlbmFyaW8gMyBmdXR1cmUgdmFyaWFibGVzCmBgYHtyIHMzX2Z2X2xifQpzM19mdl9sYiA8LSBzM192YXJzX2xhbmRpc19mdXQgJT4lCiAgc2FwcGx5KCJbWyIsIGxibHYpICU+JQogIG1hcHBseShjbGltX2Z2X2NjMCwgRlVOID0gc3RhY2spCgpzYXZlKHMzX2Z2X2xiLCBmaWxlID0gIm91dHB1dC9oYWJpdGF0X3ZhcnMvczNfZnZfbGIiKQpgYGAKCgojIyMgU2NlbmFyaW8gNAoKIyMjIyBHcmVhdGVyIEdsaWRlcgoKIyMjIyMgU2NlbmFyaW8gNCBpbml0aWFsIHZhcmlhYmxlcwpgYGB7ciBzNF9pdl9nZ30KczRfaXZfZ2cgPC0gc3RhY2soczRfdmFyc19sYW5kaXNfaW5pdFtbYyhnZ2x2KV1dLCBjbGltX2l2KQoKc2F2ZShzNF9pdl9nZywgZmlsZSA9ICJvdXRwdXQvaGFiaXRhdF92YXJzL3M0X2l2X2dnIikKYGBgCgojIyMjIyBTY2VuYWlvIDQgbW9kZWwgZGF0YQpgYGB7cn0KczRfbWRfZ2cgPC0gczRfaXZfZ2cgJT4lCiAgcmFzdGVyOjpleHRyYWN0KHkgPSBzdF9jb29yZGluYXRlcyhnZ19wYV9jaCkpICU+JQogIGNiaW5kKCJQQSIgPSBnZ19wYV9jaCRQQSwgLikgJT4lCiAgYXMuZGF0YS5mcmFtZSAlPiUKICBuYS5vbWl0IAoKczRfbWRfZ2cKCnNhdmUoczRfbWRfZ2csIGZpbGUgPSAib3V0cHV0L2hhYml0YXRfdmFycy9zNF9tZF9nZyIpCmBgYAoKCiMjIyMjIFNjZW5hcmlvIDQgZnV0dXJlIHZhcmlhYmxlcwpgYGB7ciBzNF9mdl9nZ30KczRfZnZfZ2cgPC0gczRfdmFyc19sYW5kaXNfZnV0ICU+JQogIHNhcHBseSgiW1siLCBnZ2x2KSAlPiUKICBtYXBwbHkoY2xpbV9mdl80LjUsIEZVTiA9IHN0YWNrKQoKc2F2ZShzNF9mdl9nZywgZmlsZSA9ICJvdXRwdXQvaGFiaXRhdF92YXJzL3M0X2Z2X2dnIikKYGBgCgoKIyMjIyBMZWFkYmVhdGVyJ3MgUG9zc3VtCgojIyMjIyBTY2VuYXJpbyA0IGluaXRpYWwgdmFyaWFibGVzCmBgYHtyIHM0X2l2X2xifQpzNF9pdl9sYiA8LSBzdGFjayhzNF92YXJzX2xhbmRpc19pbml0W1tjKGxibHYpXV0sIGNsaW1faXYpCgpzYXZlKHM0X2l2X2xiLCBmaWxlID0gIm91dHB1dC9oYWJpdGF0X3ZhcnMvczRfaXZfbGIiKQpgYGAKCiMjIyMjIFNjZW5haW8gNCBtb2RlbCBkYXRhCmBgYHtyfQpzNF9tZF9sYiA8LSBzNF9pdl9sYiAlPiUKICByYXN0ZXI6OmV4dHJhY3QoeSA9IHN0X2Nvb3JkaW5hdGVzKGxiX3BhX2NoKSkgJT4lCiAgY2JpbmQoIlBBIiA9IGxiX3BhX2NoJFBBLCAuKSAlPiUKICBhcy5kYXRhLmZyYW1lICU+JQogIG5hLm9taXQgCgpzNF9tZF9sYgoKc2F2ZShzNF9tZF9sYiwgZmlsZSA9ICJvdXRwdXQvaGFiaXRhdF92YXJzL3M0X21kX2xiIikKYGBgCgoKIyMjIyMgU2NlbmFyaW8gNCBmdXR1cmUgdmFyaWFibGVzCmBgYHtyIHM0X2Z2X2xifQpzNF9mdl9sYiA8LSBzNF92YXJzX2xhbmRpc19mdXQgJT4lCiAgc2FwcGx5KCJbWyIsIGxibHYpICU+JQogIG1hcHBseShjbGltX2Z2XzQuNSwgRlVOID0gc3RhY2spCgpzYXZlKHM0X2Z2X2xiLCBmaWxlID0gIm91dHB1dC9oYWJpdGF0X3ZhcnMvczRfZnZfbGIiKQpgYGAKCgojIERpc3RyaWJ1dGlvbiBtb2RlbCBmaXQgYW5kIHByZWRpY3Rpb24KCiMjIEdyZWF0ZXIgR2xpZGVyCgojIyMgU2NlbmFyaW8gMQpgYGB7ciBzMV9tb2RfZ2d9CnMxX21vZF9nZyA8LSBnYm0uc3RlcChkYXRhID0gczFfbWRfZ2csIGdibS54ID0gMjo4LCBnYm0ueSA9IDEsIGZhbWlseSA9ICJiZXJub3VsbGkiLCB0cmVlLmNvbXBsZXhpdHkgPSA1LCBsZWFybmluZy5yYXRlID0gMC4wMDEsIHN0ZXAuc2l6ZSA9IDEsIGJhZy5mcmFjdGlvbiA9IDAuNSwgcHJldi5zdHJhdGlmeSA9IEZBTFNFLCB2ZXJib3NlID0gRkFMU0UsIG1heC50cmVlcyA9IDEwMDApCmBgYApgYGB7ciBzdW1hcnkgczFfbW9kX2dnfQpzdW1tYXJ5KHMxX21vZF9nZykKYGBgCgpgYGB7ciBzMV9pcF9nZ30KI3MxX2lwX2dnIDwtIHByZWRpY3QoczFfaXZfZ2csIHMxX21vZF9nZywgdHlwZSA9ICJyZXNwb25zZSIsIG4udHJlZXMgPSBzMV9tb2RfZ2ckZ2JtLmNhbGwkYmVzdC50cmVlcywgZmlsZW5hbWUgPSAib3V0cHV0L2hhYml0YXRfcHJlZC9zMV9mcF9nZy0wMDAudGlmIikKCiN3cml0ZVJhc3RlcihzMV9pcF9nZywgIm91dHB1dC9oYWJpdGF0X3ByZWQvczFfaXBfZ2cudGlmIiwgb3ZlcndyaXRlID0gVFJVRSkKczFfaXBfZ2cgPC0gcmFzdGVyKHggPSAib3V0cHV0L2hhYml0YXRfcHJlZC9zMV9pcF9nZy50aWYiKQoKcGxvdChzMV9pcF9nZykKYGBgCgpgYGB7ciBzMV9mcF9nZ30KcmVnaXN0ZXJEb01DKGNvcmVzID0gMjApCgpzMV9mcF9nZyA8LSBmb3JlYWNoKGkgPSBzZXFfbGVuKGxlbmd0aChzMV9mdl9nZykpKSAlZG9wYXIlIHsKICBwcmVkaWN0KHMxX2Z2X2dnW1tpXV0sCiAgICAgICAgICBzMV9tb2RfZ2csCiAgICAgICAgICB0eXBlID0gInJlc3BvbnNlIiwKICAgICAgICAgIG4udHJlZXMgPSBzMV9tb2RfZ2ckZ2JtLmNhbGwkYmVzdC50cmVlcywKICAgICAgICAgIGZpbGVuYW1lID0gcGFzdGUwKCJvdXRwdXQvaGFiaXRhdF9wcmVkL3MxX2ZwX2dnLSIsIHNwcmludGYoIiUwM2QiLCBpKSwgIi50aWYiKSwKICAgICAgICAgIG92ZXJ3cml0ZSA9IFRSVUUpCn0KCnMxX2ZwX2dnIDwtIHN0YWNrKHMxX2ZwX2dnKQpgYGAKCmBgYHtyIHNhdmUgczFfZnBfZ2d9CnNhdmUoczFfZnBfZ2csIGZpbGUgPSAib3V0cHV0L2hhYml0YXRfcHJlZC9zMV9mcF9nZyIpCndyaXRlUmFzdGVyKHMxX2ZwX2dnLCBmaWxlbmFtZSA9ICJvdXRwdXQvaGFiaXRhdF9wcmVkL3MxX2ZwX2dnLnRpZiIpCmBgYAoKCiMjIyBTY2VuYXJpbyAzCmBgYHtyIHMzX21vZF9nZ30KczNfbW9kX2dnIDwtIGdibS5zdGVwKGRhdGEgPSBzM19tZF9nZywgZ2JtLnggPSAzOjcsIGdibS55ID0gMSwgZmFtaWx5ID0gImJlcm5vdWxsaSIsIHRyZWUuY29tcGxleGl0eSA9IDUsIGxlYXJuaW5nLnJhdGUgPSAwLjAwMSwgc3RlcC5zaXplID0gMSwgYmFnLmZyYWN0aW9uID0gMC41LCBwcmV2LnN0cmF0aWZ5ID0gRkFMU0UsIHZlcmJvc2UgPSBGQUxTRSwgbWF4LnRyZWVzID0gMTAwMCkKYGBgCmBgYHtyIHN1bWFyeSBzM19tb2RfZ2d9CnN1bW1hcnkoczNfbW9kX2dnKQpgYGAKCmBgYHtyIHMzX2lwX2dnfQogIyBzM19pcF9nZyA8LSBwcmVkaWN0KHMzX2l2X2dnLCBzM19tb2RfZ2csIHR5cGUgPSAicmVzcG9uc2UiLCBuLnRyZWVzID0gczNfbW9kX2dnJGdibS5jYWxsJGJlc3QudHJlZXMsIGZpbGVuYW1lID0ib3V0cHV0L2hhYml0YXRfcHJlZC9zM19mcF9nZy0wMDAudGlmIikKCiAjIHdyaXRlUmFzdGVyKHMzX2lwX2dnLCAib3V0cHV0L2hhYml0YXRfcHJlZC9zM19pcF9nZy50aWYiLCBvdmVyd3JpdGUgPSBUUlVFKQoKczNfaXBfZ2cgPC0gcmFzdGVyKHggPSAib3V0cHV0L2hhYml0YXRfcHJlZC9zM19pcF9nZy50aWYiKQoKcGxvdChzM19pcF9nZykKYGBgCgpgYGB7ciBzM19mcF9nZ30KcmVnaXN0ZXJEb01DKGNvcmVzID0gMjApCgpzM19mcF9nZyA8LSBmb3JlYWNoKGkgPSBzZXFfbGVuKGxlbmd0aChzM19mdl9nZykpKSAlZG9wYXIlIHsKICBwcmVkaWN0KHMzX2Z2X2dnW1tpXV0sCiAgICAgICAgICBzM19tb2RfZ2csCiAgICAgICAgICB0eXBlID0gInJlc3BvbnNlIiwKICAgICAgICAgIG4udHJlZXMgPSBzM19tb2RfZ2ckZ2JtLmNhbGwkYmVzdC50cmVlcywKICAgICAgICAgIGZpbGVuYW1lID0gcGFzdGUwKCJvdXRwdXQvaGFiaXRhdF9wcmVkL3MzX2ZwX2dnLSIsIHNwcmludGYoIiUwM2QiLCBpKSwgIi50aWYiKSwKICAgICAgICAgIG92ZXJ3cml0ZSA9IFRSVUUpCn0KCnMzX2ZwX2dnIDwtIHN0YWNrKHMzX2ZwX2dnKQpgYGAKCmBgYHtyIHNhdmUgczNfZnBfZ2d9CnNhdmUoczNfZnBfZ2csIGZpbGUgPSAib3V0cHV0L2hhYml0YXRfcHJlZC9zM19mcF9nZyIpCndyaXRlUmFzdGVyKHMzX2ZwX2dnLCBmaWxlbmFtZSA9ICJvdXRwdXQvaGFiaXRhdF9wcmVkL3MzX2ZwX2dnLnRpZiIpCmBgYAoKIyMjIFNjZW5hcmlvIDQKYGBge3IgczRfbW9kX2dnfQpzNF9tb2RfZ2cgPC0gZ2JtLnN0ZXAoZGF0YSA9IHM0X21kX2dnLCBnYm0ueCA9IDI6OCwgZ2JtLnkgPSAxLCBmYW1pbHkgPSAiYmVybm91bGxpIiwgdHJlZS5jb21wbGV4aXR5ID0gNSwgbGVhcm5pbmcucmF0ZSA9IDAuMDAxLCBzdGVwLnNpemUgPSAxLCBiYWcuZnJhY3Rpb24gPSAwLjUsIHByZXYuc3RyYXRpZnkgPSBGQUxTRSwgdmVyYm9zZSA9IEZBTFNFLCBtYXgudHJlZXMgPSAxMDAwKQpgYGAKYGBge3Igc3VtYXJ5IHM0X21vZF9nZ30Kc3VtbWFyeShzNF9tb2RfZ2cpCmBgYAoKYGBge3IgczRfaXBfZ2d9CiMgczRfaXBfZ2cgPC0gcHJlZGljdChzNF9pdl9nZywgczRfbW9kX2dnLCB0eXBlID0gInJlc3BvbnNlIiwgbi50cmVlcyA9IHM0X21vZF9nZyRnYm0uY2FsbCRiZXN0LnRyZWVzLCAgZmlsZW5hbWUgPSAib3V0cHV0L2hhYml0YXRfcHJlZC80X2ZwX2dnLTAwMC50aWYiKQoKIyB3cml0ZVJhc3RlcihzNF9pcF9nZywgIm91dHB1dC9oYWJpdGF0X3ByZWQvczRfaXBfZ2cudGlmIiwgb3ZlcndyaXRlID0gVFJVRSkKCnM0X2lwX2dnIDwtIHJhc3Rlcih4ID0gIm91dHB1dC9oYWJpdGF0X3ByZWQvczRfaXBfZ2cudGlmIikKCnBsb3QoczRfaXBfZ2cpCmBgYAoKYGBge3IgczRfZnBfZ2d9CnJlZ2lzdGVyRG9NQyhjb3JlcyA9IDIwKQoKczRfZnBfZ2cgPC0gZm9yZWFjaChpID0gc2VxX2xlbihsZW5ndGgoczRfZnZfZ2cpKSkgJWRvcGFyJSB7CiAgcHJlZGljdChzNF9mdl9nZ1tbaV1dLAogICAgICAgICAgczRfbW9kX2dnLAogICAgICAgICAgdHlwZSA9ICJyZXNwb25zZSIsCiAgICAgICAgICBuLnRyZWVzID0gczRfbW9kX2dnJGdibS5jYWxsJGJlc3QudHJlZXMsCiAgICAgICAgICBmaWxlbmFtZSA9IHBhc3RlMCgib3V0cHV0L2hhYml0YXRfcHJlZC9zNF9mcF9nZy0iLCBzcHJpbnRmKCIlMDNkIiwgaSksICIudGlmIiksCiAgICAgICAgICBvdmVyd3JpdGUgPSBUUlVFKQp9CgpzNF9mcF9nZyA8LSBzdGFjayhzNF9mcF9nZykKYGBgCgpgYGB7ciBzYXZlIHM0X2ZwX2dnfQpzYXZlKHM0X2ZwX2dnLCBmaWxlID0gIm91dHB1dC9oYWJpdGF0X3ByZWQvczRfZnBfZ2ciKQp3cml0ZVJhc3RlcihzNF9mcF9nZywgZmlsZW5hbWUgPSAib3V0cHV0L2hhYml0YXRfcHJlZC9zNF9mcF9nZy50aWYiKQpgYGAKCgojIyBMZWFkYmVhdGVyJ3MgUG9zc3VtCgoKIyMjIFNjZW5hcmlvIDEKYGBge3IgczFfbW9kX2xifQpzMV9tb2RfbGIgPC0gZ2JtLnN0ZXAoZGF0YSA9IHMxX21kX2xiLCBnYm0ueCA9IDI6NywgZ2JtLnkgPSAxLCBmYW1pbHkgPSAiYmVybm91bGxpIiwgdHJlZS5jb21wbGV4aXR5ID0gNSwgbGVhcm5pbmcucmF0ZSA9IDAuMDAxLCBzdGVwLnNpemUgPSAxLCBiYWcuZnJhY3Rpb24gPSAwLjUsIHByZXYuc3RyYXRpZnkgPSBGQUxTRSwgdmVyYm9zZSA9IEZBTFNFLCBtYXgudHJlZXMgPSAxMDAwKQpgYGAKYGBge3Igc3VtYXJ5IHMxX21vZF9sYn0Kc3VtbWFyeShzMV9tb2RfbGIpCmBgYAoKYGBge3IgczFfaXBfbGJ9CiMgczFfaXBfbGIgPC0gcHJlZGljdChzMV9pdl9sYiwgczFfbW9kX2xiLCB0eXBlID0gInJlc3BvbnNlIiwgbi50cmVlcyA9IHMxX21vZF9sYiRnYm0uY2FsbCRiZXN0LnRyZWVzLCBmaWxlbmFtZSA9ICJvdXRwdXQvaGFiaXRhdF9wcmVkL3MxX2ZwX2xiLTAwMC50aWYiKQoKIyB3cml0ZVJhc3RlcihzMV9pcF9sYiwgIm91dHB1dC9oYWJpdGF0X3ByZWQvczFfaXBfbGIudGlmIiwgb3ZlcndyaXRlID0gVFJVRSkKCnMxX2lwX2xiIDwtIHJhc3Rlcih4ID0gIm91dHB1dC9oYWJpdGF0X3ByZWQvczFfaXBfbGIudGlmIikKCnBsb3QoczFfaXBfbGIpCmBgYAoKYGBge3IgczFfZnBfbGJ9CnJlZ2lzdGVyRG9NQyhjb3JlcyA9IDIwKQoKczFfZnBfbGIgPC0gZm9yZWFjaChpID0gc2VxX2xlbihsZW5ndGgoczFfZnZfbGIpKSkgJWRvcGFyJSB7CiAgcHJlZGljdChzMV9mdl9sYltbaV1dLAogICAgICAgICAgczFfbW9kX2xiLAogICAgICAgICAgdHlwZSA9ICJyZXNwb25zZSIsCiAgICAgICAgICBuLnRyZWVzID0gczFfbW9kX2xiJGdibS5jYWxsJGJlc3QudHJlZXMsCiAgICAgICAgICBmaWxlbmFtZSA9IHBhc3RlMCgib3V0cHV0L2hhYml0YXRfcHJlZC9zMV9mcF9sYi0iLCBzcHJpbnRmKCIlMDNkIiwgaSksICIudGlmIiksCiAgICAgICAgICBvdmVyd3JpdGUgPSBUUlVFKQp9CgpzMV9mcF9sYiA8LSBzdGFjayhzMV9mcF9sYikKYGBgCgpgYGB7ciBzYXZlIHMxX2ZwX2xifQpzYXZlKHMxX2ZwX2xiLCBmaWxlID0gIm91dHB1dC9oYWJpdGF0X3ByZWQvczFfZnBfbGIiKQp3cml0ZVJhc3RlcihzMV9mcF9sYiwgZmlsZW5hbWUgPSAib3V0cHV0L2hhYml0YXRfcHJlZC9zMV9mcF9sYi50aWYiKQpgYGAKCiMjIyBTY2VuYXJpbyAzCmBgYHtyIHMzX21vZF9sYn0KczNfbW9kX2xiIDwtIGdibS5zdGVwKGRhdGEgPSBzM19tZF9sYiwgZ2JtLnggPSAyOjcsIGdibS55ID0gMSwgZmFtaWx5ID0gImJlcm5vdWxsaSIsIHRyZWUuY29tcGxleGl0eSA9IDUsIGxlYXJuaW5nLnJhdGUgPSAwLjAwMSwgc3RlcC5zaXplID0gMSwgYmFnLmZyYWN0aW9uID0gMC41LCBwcmV2LnN0cmF0aWZ5ID0gRkFMU0UsIHZlcmJvc2UgPSBGQUxTRSwgbWF4LnRyZWVzID0gMTAwMCkKYGBgCmBgYHtyIHN1bWFyeSBzM19tb2RfbGJ9CnN1bW1hcnkoczNfbW9kX2xiKQpgYGAKCmBgYHtyIHMzX2lwX2xifQojIHMzX2lwX2xiIDwtIHByZWRpY3QoczNfaXZfbGIsIHMzX21vZF9sYiwgdHlwZSA9ICJyZXNwb25zZSIsIG4udHJlZXMgPSBzM19tb2RfbGIkZ2JtLmNhbGwkYmVzdC50cmVlcywgZmlsZW5hbWUgPSAib3V0cHV0L2hhYml0YXRfcHJlZC9zM19mcF9sYi0wMDAudGlmIikKCiMgd3JpdGVSYXN0ZXIoczNfaXBfbGIsICJvdXRwdXQvaGFiaXRhdF9wcmVkL3MzX2lwX2xiLnRpZiIsIG92ZXJ3cml0ZSA9IFRSVUUpCgpzM19pcF9sYiA8LSByYXN0ZXIoeCA9ICJvdXRwdXQvaGFiaXRhdF9wcmVkL3MzX2lwX2xiLnRpZiIpCgpwbG90KHMzX2lwX2xiKQpgYGAKCmBgYHtyIHMzX2ZwX2xifQpyZWdpc3RlckRvTUMoY29yZXMgPSAyMCkKCnMzX2ZwX2xiIDwtIGZvcmVhY2goaSA9IHNlcV9sZW4obGVuZ3RoKHMzX2Z2X2xiKSkpICVkb3BhciUgewogIHByZWRpY3QoczNfZnZfbGJbW2ldXSwKICAgICAgICAgIHMzX21vZF9sYiwKICAgICAgICAgIHR5cGUgPSAicmVzcG9uc2UiLAogICAgICAgICAgbi50cmVlcyA9IHMzX21vZF9sYiRnYm0uY2FsbCRiZXN0LnRyZWVzLAogICAgICAgICAgZmlsZW5hbWUgPSBwYXN0ZTAoIm91dHB1dC9oYWJpdGF0X3ByZWQvczNfZnBfbGItIiwgc3ByaW50ZigiJTAzZCIsIGkpLCAiLnRpZiIpLAogICAgICAgICAgb3ZlcndyaXRlID0gVFJVRSkKfQoKczNfZnBfbGIgPC0gc3RhY2soczNfZnBfbGIpCmBgYAoKYGBge3Igc2F2ZSBzM19mcF9sYn0Kc2F2ZShzM19mcF9sYiwgZmlsZSA9ICJvdXRwdXQvaGFiaXRhdF9wcmVkL3MzX2ZwX2xiIikKd3JpdGVSYXN0ZXIoczNfZnBfbGIsIGZpbGVuYW1lID0gIm91dHB1dC9oYWJpdGF0X3ByZWQvczNfZnBfbGIudGlmIikKYGBgCgojIyMgU2NlbmFyaW8gNApgYGB7ciBzNF9tb2RfbGJ9CnM0X21vZF9sYiA8LSBnYm0uc3RlcChkYXRhID0gczRfbWRfbGIsIGdibS54ID0gMjo3LCBnYm0ueSA9IDEsIGZhbWlseSA9ICJiZXJub3VsbGkiLCB0cmVlLmNvbXBsZXhpdHkgPSA1LCBsZWFybmluZy5yYXRlID0gMC4wMDEsIHN0ZXAuc2l6ZSA9IDEsIGJhZy5mcmFjdGlvbiA9IDAuNSwgcHJldi5zdHJhdGlmeSA9IEZBTFNFLCB2ZXJib3NlID0gRkFMU0UsIG1heC50cmVlcyA9IDEwMDApCmBgYApgYGB7ciBzdW1hcnkgczRfbW9kX2xifQpzdW1tYXJ5KHM0X21vZF9sYikKYGBgCgpgYGB7ciBzNF9pcF9sYn0KIyBzNF9pcF9sYiA8LSBwcmVkaWN0KHM0X2l2X2xiLCBzNF9tb2RfbGIsIHR5cGUgPSAicmVzcG9uc2UiLCBuLnRyZWVzID0gczRfbW9kX2xiJGdibS5jYWxsJGJlc3QudHJlZXMsIGZpbGVuYW1lID0gIm91dHB1dC9oYWJpdGF0X3ByZWQvczRfZnBfbGItMDAwLnRpZiIpCgojIHdyaXRlUmFzdGVyKHM0X2lwX2xiLCAib3V0cHV0L2hhYml0YXRfcHJlZC9zNF9pcF9sYi50aWYiLCBvdmVyd3JpdGUgPSBUUlVFKQoKczRfaXBfbGIgPC0gcmFzdGVyKHggPSAib3V0cHV0L2hhYml0YXRfcHJlZC9zNF9pcF9sYi50aWYiKQoKcGxvdChzNF9pcF9sYikKYGBgCgpgYGB7ciBzNF9mcF9sYn0KcmVnaXN0ZXJEb01DKGNvcmVzID0gMjApCgpzNF9mcF9sYiA8LSBmb3JlYWNoKGkgPSBzZXFfbGVuKGxlbmd0aChzNF9mdl9sYikpKSAlZG9wYXIlIHsKICBwcmVkaWN0KHM0X2Z2X2xiW1tpXV0sCiAgICAgICAgICBzNF9tb2RfbGIsCiAgICAgICAgICB0eXBlID0gInJlc3BvbnNlIiwKICAgICAgICAgIG4udHJlZXMgPSBzNF9tb2RfbGIkZ2JtLmNhbGwkYmVzdC50cmVlcywKICAgICAgICAgIGZpbGVuYW1lID0gcGFzdGUwKCJvdXRwdXQvaGFiaXRhdF9wcmVkL3M0X2ZwX2xiLSIsIHNwcmludGYoIiUwM2QiLCBpKSwgIi50aWYiKSwKICAgICAgICAgIG92ZXJ3cml0ZSA9IFRSVUUpCn0KCnM0X2ZwX2xiIDwtIHN0YWNrKHM0X2ZwX2xiKQpgYGAKCmBgYHtyIHNhdmUgczRfZnBfbGJ9CnNhdmUoczRfZnBfbGIsIGZpbGUgPSAib3V0cHV0L2hhYml0YXRfcHJlZC9zNF9mcF9sYiIpCndyaXRlUmFzdGVyKHM0X2ZwX2xiLCBmaWxlbmFtZSA9ICJvdXRwdXQvaGFiaXRhdF9wcmVkL3M0X2ZwX2xiLnRpZiIpCmBgYAoKCgojIFBvcHVsYXRpb24gdmlhYmlsaXR5IGFuYWx5c2lzCgojIyBHcmVhdGVyIEdsaWRlcgpgYGB7cn0KZ2dfdHJhbnNfbWF0IDwtIG1hdHJpeChjKDAuMDAsMC4wMCwwLjI1LAogICAgICAgICAgICAgICAgICAgICAgICAgMC41MCwwLjAwLDAuMDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAwLjAwLDAuODUsMC44NSksCiAgICAgICAgICAgICAgICAgICAgICAgbnJvdyA9IDMsIG5jb2wgPSAzLCBieXJvdyA9IFRSVUUpICMgYmFzZWQgb24gUG9zc2luZ2hhbSBldCBhbCAxOTk0CmNvbG5hbWVzKGdnX3RyYW5zX21hdCkgPC0gcm93bmFtZXMoZ2dfdHJhbnNfbWF0KSA8LSBjKCdOZXdib3JuJywnSnV2ZW5pbGUnLCdBZHVsdCcpCgpnZ19zdGFibGVfc3RhdGVzIDwtIGFicyggZWlnZW4oZ2dfdHJhbnNfbWF0KSR2ZWN0b3JzWywxXSAvIGJhc2U6OnN1bShlaWdlbihnZ190cmFuc19tYXQpJHZlY3RvcnNbLDFdKSApIApgYGAKCgojIyMgU2NlbmFyaW8gMQpgYGB7cn0KczFfaHNfZ2cgPC0gc3RhY2soczFfaXBfZ2csIHMxX2ZwX2dnKQoKZm9yKGkgaW4gMTo1MSl7CiAgczFfaHNfZ2dbW2ldXVtpcy5uYShzMV9oc19nZ1tbaV1dW10pXSA8LSAwCn0KCnMxX2hzX2dnIDwtIG1hc2soczFfaHNfZ2csIG1hc2sgPSBjaF9tYXNrKQpgYGAKCmBgYHtyfQpzMV9oYWJfa19nZyA8LSBjYWxjKHMxX2hzX2dnW1sxXV0sIGZ1biA9IGZ1bmN0aW9uKHgpe2lmKGlzLm5hKHgpKSB4IGVsc2UgcmJpbm9tKHByb2IgPSB4LCBzaXplID0gMywgbiA9IDEpfSkKCm5hbWVzKHMxX2hhYl9rX2dnKSA8LSAiY2FycnlpbmdDYXBhY2l0eSIKCnMxX2dnX3BvcE4gPC0gc3RhY2socmVwbGljYXRlKG5jb2woZ2dfdHJhbnNfbWF0KSwgczFfaGFiX2tfZ2cpKQoKczFfZ2dfcG9wTiA8LSBzMV9nZ19wb3BOKmdnX3N0YWJsZV9zdGF0ZXMKCnMxX2dnX2lkeCA8LSB3aGljaCghaXMubmEoczFfaHNfZ2dbWzFdXVtdKSAmIHMxX2hzX2dnW1sxXV1bXSA8IDAuOTUpCgpzMV9nZ19wb3AgPC0gczFfZ2dfcG9wTgpzMV9nZ19wb3BbIWlzLm5hKHMxX2dnX3BvcCldIDwtIDAKczFfZ2dfcG9wW1sxXV1bc2FtcGxlKHMxX2dnX2lkeCwgMTAwMDApXSA8LSAxCnMxX2dnX3BvcFtbMl1dW3NhbXBsZShzMV9nZ19pZHgsIDEwMDAwKV0gPC0gMQpzMV9nZ19wb3BbWzNdXVtzYW1wbGUoczFfZ2dfaWR4LCAxMDAwMCldIDwtIDEKCnMxX2dnX3BvcCA8LSBzMV9nZ19wb3AqY2hfbWFzawoKbmFtZXMoczFfZ2dfcG9wKSA8LSBjb2xuYW1lcyhnZ190cmFuc19tYXQpCgpzMV9nZ19Ub3Rwb3BOIDwtIHN1bShjZWxsU3RhdHMoczFfZ2dfcG9wLCAnc3VtJywgbmEucm0gPSBUUlVFKSkgIyBHZXQgdG90YWwgcG9wdWxhdGlvbiBzaXplIHRvIGNoZWNrIHNlbnNpYmxlCnMxX2dnX2luaXRfcG9wX3NpemUgPC0gc3VtKHMxX2dnX3BvcCkKYGBgCgpgYGB7cn0KczFfZ2dfbGFuZHNjYXBlIDwtIGxhbmRzY2FwZShwb3B1bGF0aW9uID0gczFfZ2dfcG9wLAogICAgICAgICAgICAgICAgICAgICAgICAgIHN1aXRhYmlsaXR5ID0gczFfaHNfZ2csCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FycnlpbmdfY2FwYWNpdHkgPSBzMV9oYWJfa19nZykKCnMxX2dnX3BvcF9keW5hbWljcyA8LSBwb3B1bGF0aW9uX2R5bmFtaWNzKGNoYW5nZSA9IGdyb3d0aCh0cmFuc2l0aW9uX21hdHJpeCA9IGdnX3RyYW5zX21hdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbF9zdG9jaGFzdGljaXR5ID0gMC4xKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGVyc2FsID0gZmFzdF9kaXNwZXJzYWwoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGVyc2FsX2tlcm5lbCA9IGV4cG9uZW50aWFsX2Rpc3BlcnNhbF9rZXJuZWwoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0YW5jZV9kZWNheSA9IDgwMDApKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZpY2F0aW9uID0gTlVMTCkKYGBgCgpgYGB7cn0KcGxhbihzZXF1ZW50aWFsLCB3b3JrZXJzID0gMSkKczFfZ2dfcmVzdWx0c18xXzUwIDwtIHNpbXVsYXRpb24obGFuZHNjYXBlID0gczFfZ2dfbGFuZHNjYXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgcG9wdWxhdGlvbl9keW5hbWljcyA9IHMxX2dnX3BvcF9keW5hbWljcywKICAgICAgICAgICAgICAgICAgICAgICAgIGhhYml0YXRfZHluYW1pY3MgPSBOVUxMLAogICAgICAgICAgICAgICAgICAgICAgICAgdGltZXN0ZXBzID0gNTAsCiAgICAgICAgICAgICAgICAgICAgICAgICByZXBsaWNhdGVzID0gMSkKCgpzYXZlUkRTKG9iamVjdCA9IHMxX2dnX3Jlc3VsdHNfMV81MCwgZmlsZSA9ICJvdXRwdXQvcHZhX3Jlc3VsdHMvczFfZ2dfcmVzdWx0c18xXzUwLlJkcyIpCmBgYAoKCmBgYHtyfQpwbG90KHMxX2dnX3Jlc3VsdHNfMV81MCkKYGBgCgpgYGB7cn0KcGxvdChzMV9nZ19yZXN1bHRzXzFfNTBbMV0sIHR5cGUgPSAicmFzdGVyIiwgc3RhZ2VzID0gMCwgdGltZXN0ZXBzID0gYygxOjUpKQpgYGAKCiMjIyBTY2VuYXJpbyAzCmBgYHtyfQpzM19oc19nZyA8LSBzdGFjayhzM19pcF9nZywgczNfZnBfZ2cpCgpmb3IoaSBpbiAxOjUxKXsKICBzM19oc19nZ1tbaV1dW2lzLm5hKHMzX2hzX2dnW1tpXV1bXSldIDwtIDAKfQoKczNfaHNfZ2cgPC0gbWFzayhzM19oc19nZywgbWFzayA9IGNoX21hc2spCmBgYAoKYGBge3J9CnMzX2hhYl9rX2dnIDwtIGNhbGMoczNfaHNfZ2dbWzFdXSwgZnVuID0gZnVuY3Rpb24oeCl7aWYoaXMubmEoeCkpIHggZWxzZSByYmlub20ocHJvYiA9IHgsIHNpemUgPSAzLCBuID0gMSl9KQoKbmFtZXMoczNfaGFiX2tfZ2cpIDwtICJjYXJyeWluZ0NhcGFjaXR5IgoKczNfZ2dfcG9wTiA8LSBzdGFjayhyZXBsaWNhdGUobmNvbChnZ190cmFuc19tYXQpLCBzM19oYWJfa19nZykpCgpzM19nZ19wb3BOIDwtIHMzX2dnX3BvcE4qZ2dfc3RhYmxlX3N0YXRlcwoKczNfZ2dfaWR4IDwtIHdoaWNoKCFpcy5uYShzM19oc19nZ1tbMV1dW10pICYgczNfaHNfZ2dbWzFdXVtdIDwgMC45NSkKCnMzX2dnX3BvcCA8LSBzM19nZ19wb3BOCnMzX2dnX3BvcFshaXMubmEoczNfZ2dfcG9wKV0gPC0gMApzM19nZ19wb3BbWzFdXVtzYW1wbGUoczNfZ2dfaWR4LCAxMDAwMCldIDwtIDEKczNfZ2dfcG9wW1syXV1bc2FtcGxlKHMzX2dnX2lkeCwgMTAwMDApXSA8LSAxCnMzX2dnX3BvcFtbM11dW3NhbXBsZShzM19nZ19pZHgsIDEwMDAwKV0gPC0gMQoKczNfZ2dfcG9wIDwtIHMzX2dnX3BvcCpjaF9tYXNrCgpuYW1lcyhzM19nZ19wb3ApIDwtIGNvbG5hbWVzKGdnX3RyYW5zX21hdCkKCnMzX2dnX1RvdHBvcE4gPC0gc3VtKGNlbGxTdGF0cyhzM19nZ19wb3AsICdzdW0nLCBuYS5ybSA9IFRSVUUpKSAjIEdldCB0b3RhbCBwb3B1bGF0aW9uIHNpemUgdG8gY2hlY2sgc2Vuc2libGUKczNfZ2dfaW5pdF9wb3Bfc2l6ZSA8LSBzdW0oczNfZ2dfcG9wKQpgYGAKCmBgYHtyfQpzM19nZ19sYW5kc2NhcGUgPC0gbGFuZHNjYXBlKHBvcHVsYXRpb24gPSBzM19nZ19wb3AsCiAgICAgICAgICAgICAgICAgICAgICAgICAgc3VpdGFiaWxpdHkgPSBzM19oc19nZywKICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJyeWluZ19jYXBhY2l0eSA9IHMzX2hhYl9rX2dnKQoKczNfZ2dfcG9wX2R5bmFtaWNzIDwtIHBvcHVsYXRpb25fZHluYW1pY3MoY2hhbmdlID0gZ3Jvd3RoKHRyYW5zaXRpb25fbWF0cml4ID0gZ2dfdHJhbnNfbWF0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2xvYmFsX3N0b2NoYXN0aWNpdHkgPSAwLjEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNwZXJzYWwgPSBmYXN0X2Rpc3BlcnNhbCgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNwZXJzYWxfa2VybmVsID0gZXhwb25lbnRpYWxfZGlzcGVyc2FsX2tlcm5lbCgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RhbmNlX2RlY2F5ID0gODAwMCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RpZmljYXRpb24gPSBOVUxMKQpgYGAKCmBgYHtyfQpwbGFuKHNlcXVlbnRpYWwsIHdvcmtlcnMgPSAxKQpzM19nZ19yZXN1bHRzXzFfNTAgPC0gc2ltdWxhdGlvbihsYW5kc2NhcGUgPSBzM19nZ19sYW5kc2NhcGUsCiAgICAgICAgICAgICAgICAgICAgICAgICBwb3B1bGF0aW9uX2R5bmFtaWNzID0gczNfZ2dfcG9wX2R5bmFtaWNzLAogICAgICAgICAgICAgICAgICAgICAgICAgaGFiaXRhdF9keW5hbWljcyA9IE5VTEwsCiAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lc3RlcHMgPSA1MCwKICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxpY2F0ZXMgPSAxKQoKCnNhdmVSRFMob2JqZWN0ID0gczNfZ2dfcmVzdWx0c18xXzUwLCBmaWxlID0gIm91dHB1dC9wdmFfcmVzdWx0cy9zM19nZ19yZXN1bHRzXzFfNTAuUmRzIikKYGBgCgoKYGBge3J9CnBsb3QoczNfZ2dfcmVzdWx0c18xXzUwKQpgYGAKCmBgYHtyfQpwbG90KHMzX2dnX3Jlc3VsdHNfMV81MFsxXSwgdHlwZSA9ICJyYXN0ZXIiLCBzdGFnZXMgPSAwLCB0aW1lc3RlcHMgPSBjKDE6NSkpCmBgYAoKIyMjIFNjZW5hcmlvIDQKYGBge3J9CnM0X2hzX2dnIDwtIHN0YWNrKHM0X2lwX2dnLCBzNF9mcF9nZykKCmZvcihpIGluIDE6NTEpewogIHM0X2hzX2dnW1tpXV1baXMubmEoczRfaHNfZ2dbW2ldXVtdKV0gPC0gMAp9CgpzNF9oc19nZyA8LSBtYXNrKHM0X2hzX2dnLCBtYXNrID0gY2hfbWFzaykKYGBgCgpgYGB7cn0KczRfaGFiX2tfZ2cgPC0gY2FsYyhzNF9oc19nZ1tbMV1dLCBmdW4gPSBmdW5jdGlvbih4KXtpZihpcy5uYSh4KSkgeCBlbHNlIHJiaW5vbShwcm9iID0geCwgc2l6ZSA9IDMsIG4gPSAxKX0pCgpuYW1lcyhzNF9oYWJfa19nZykgPC0gImNhcnJ5aW5nQ2FwYWNpdHkiCgpzNF9nZ19wb3BOIDwtIHN0YWNrKHJlcGxpY2F0ZShuY29sKGdnX3RyYW5zX21hdCksIHM0X2hhYl9rX2dnKSkKCnM0X2dnX3BvcE4gPC0gczRfZ2dfcG9wTipnZ19zdGFibGVfc3RhdGVzCgpzNF9nZ19pZHggPC0gd2hpY2goIWlzLm5hKHM0X2hzX2dnW1sxXV1bXSkgJiBzNF9oc19nZ1tbMV1dW10gPCAwLjk1KQoKczRfZ2dfcG9wIDwtIHM0X2dnX3BvcE4KczRfZ2dfcG9wWyFpcy5uYShzNF9nZ19wb3ApXSA8LSAwCnM0X2dnX3BvcFtbMV1dW3NhbXBsZShzNF9nZ19pZHgsIDEwMDAwKV0gPC0gMQpzNF9nZ19wb3BbWzJdXVtzYW1wbGUoczRfZ2dfaWR4LCAxMDAwMCldIDwtIDEKczRfZ2dfcG9wW1szXV1bc2FtcGxlKHM0X2dnX2lkeCwgMTAwMDApXSA8LSAxCgpzNF9nZ19wb3AgPC0gczRfZ2dfcG9wKmNoX21hc2sKCm5hbWVzKHM0X2dnX3BvcCkgPC0gY29sbmFtZXMoZ2dfdHJhbnNfbWF0KQoKczRfZ2dfVG90cG9wTiA8LSBzdW0oY2VsbFN0YXRzKHM0X2dnX3BvcCwgJ3N1bScsIG5hLnJtID0gVFJVRSkpICMgR2V0IHRvdGFsIHBvcHVsYXRpb24gc2l6ZSB0byBjaGVjayBzZW5zaWJsZQpzNF9nZ19pbml0X3BvcF9zaXplIDwtIHN1bShzNF9nZ19wb3ApCmBgYAoKYGBge3J9CnM0X2dnX2xhbmRzY2FwZSA8LSBsYW5kc2NhcGUocG9wdWxhdGlvbiA9IHM0X2dnX3BvcCwKICAgICAgICAgICAgICAgICAgICAgICAgICBzdWl0YWJpbGl0eSA9IHM0X2hzX2dnLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNhcnJ5aW5nX2NhcGFjaXR5ID0gczRfaGFiX2tfZ2cpCgpzNF9nZ19wb3BfZHluYW1pY3MgPC0gcG9wdWxhdGlvbl9keW5hbWljcyhjaGFuZ2UgPSBncm93dGgodHJhbnNpdGlvbl9tYXRyaXggPSBnZ190cmFuc19tYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbG9iYWxfc3RvY2hhc3RpY2l0eSA9IDAuMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BlcnNhbCA9IGZhc3RfZGlzcGVyc2FsKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BlcnNhbF9rZXJuZWwgPSBleHBvbmVudGlhbF9kaXNwZXJzYWxfa2VybmVsKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzdGFuY2VfZGVjYXkgPSA4MDAwKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGlmaWNhdGlvbiA9IE5VTEwpCmBgYAoKYGBge3J9CnBsYW4oc2VxdWVudGlhbCwgd29ya2VycyA9IDEpCnM0X2dnX3Jlc3VsdHNfMV81MCA8LSBzaW11bGF0aW9uKGxhbmRzY2FwZSA9IHM0X2dnX2xhbmRzY2FwZSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBvcHVsYXRpb25fZHluYW1pY3MgPSBzNF9nZ19wb3BfZHluYW1pY3MsCiAgICAgICAgICAgICAgICAgICAgICAgICBoYWJpdGF0X2R5bmFtaWNzID0gTlVMTCwKICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVzdGVwcyA9IDUwLAogICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGljYXRlcyA9IDEpCgoKc2F2ZVJEUyhvYmplY3QgPSBzNF9nZ19yZXN1bHRzXzFfNTAsIGZpbGUgPSAib3V0cHV0L3B2YV9yZXN1bHRzL3M0X2dnX3Jlc3VsdHNfMV81MC5SZHMiKQpgYGAKCgpgYGB7cn0KcGxvdChzNF9nZ19yZXN1bHRzXzFfNTApCmBgYAoKYGBge3J9CnBsb3QoczRfZ2dfcmVzdWx0c18xXzUwWzFdLCB0eXBlID0gInJhc3RlciIsIHN0YWdlcyA9IDAsIHRpbWVzdGVwcyA9IGMoMTo1KSkKYGBgCgoKIyMgTGVhZGJlYXRlcidzIFBvc3N1bQpgYGB7cn0KbGJfdHJhbnNfbWF0IDwtIG1hdHJpeChjKDAuMDAsIDAuMDAsIDEuMTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAwLjU5LCAwLjAwLCAwLjAwLAogICAgICAgICAgICAgICAgICAgICAgICAgMC4wMCwgMC41OSwgMC43OSksCiAgICAgICAgICAgICAgICAgICAgICAgbnJvdyA9IDMsIG5jb2wgPSAzLCBieXJvdyA9IFRSVUUpIApjb2xuYW1lcyhsYl90cmFuc19tYXQpIDwtIHJvd25hbWVzKGxiX3RyYW5zX21hdCkgPC0gYygnTmV3Ym9ybicsJ0p1dmVuaWxlJywnQWR1bHQnKQoKbGJfc3RhYmxlX3N0YXRlcyA8LSBhYnMoIGVpZ2VuKGxiX3RyYW5zX21hdCkkdmVjdG9yc1ssMV0gLyBiYXNlOjpzdW0oZWlnZW4obGJfdHJhbnNfbWF0KSR2ZWN0b3JzWywxXSkgKSAKYGBgCgojIyMgU2NlbmFyaW8gMQpgYGB7cn0KczFfaHNfbGIgPC0gc3RhY2soczFfaXBfbGIsIHMxX2ZwX2xiKQoKZm9yKGkgaW4gMTo1MSl7CiAgczFfaHNfbGJbW2ldXVtpcy5uYShzMV9oc19sYltbaV1dW10pXSA8LSAwCn0KCnMxX2hzX2xiIDwtIG1hc2soczFfaHNfbGIsIG1hc2sgPSBjaF9tYXNrKQpgYGAKCmBgYHtyfQpzMV9oYWJfa19sYiA8LSBjYWxjKHMxX2hzX2xiW1sxXV0sIGZ1biA9IGZ1bmN0aW9uKHgpe2lmKGlzLm5hKHgpKSB4IGVsc2UgcmJpbm9tKHByb2IgPSB4LCBzaXplID0gMywgbiA9IDEpfSkKCm5hbWVzKHMxX2hhYl9rX2xiKSA8LSAiY2FycnlpbmdDYXBhY2l0eSIKCnMxX2xiX3BvcE4gPC0gc3RhY2socmVwbGljYXRlKG5jb2wobGJfdHJhbnNfbWF0KSwgczFfaGFiX2tfbGIpKQoKczFfbGJfcG9wTiA8LSBzMV9sYl9wb3BOKmxiX3N0YWJsZV9zdGF0ZXMKCnMxX2xiX2lkeCA8LSB3aGljaCghaXMubmEoczFfaHNfbGJbWzFdXVtdKSAmIHMxX2hzX2xiW1sxXV1bXSA8IDAuOTUpCgpzMV9sYl9wb3AgPC0gczFfbGJfcG9wTgpzMV9sYl9wb3BbIWlzLm5hKHMxX2xiX3BvcCldIDwtIDAKczFfbGJfcG9wW1sxXV1bc2FtcGxlKHMxX2xiX2lkeCwgMzAwMCldIDwtIDEKczFfbGJfcG9wW1syXV1bc2FtcGxlKHMxX2xiX2lkeCwgMzAwMCldIDwtIDEKczFfbGJfcG9wW1szXV1bc2FtcGxlKHMxX2xiX2lkeCwgMzAwMCldIDwtIDEKCnMxX2xiX3BvcCA8LSBzMV9sYl9wb3AqY2hfbWFzawoKbmFtZXMoczFfbGJfcG9wKSA8LSBjb2xuYW1lcyhsYl90cmFuc19tYXQpCgpzMV9sYl9Ub3Rwb3BOIDwtIHN1bShjZWxsU3RhdHMoczFfbGJfcG9wLCAnc3VtJywgbmEucm0gPSBUUlVFKSkgIyBHZXQgdG90YWwgcG9wdWxhdGlvbiBzaXplIHRvIGNoZWNrIHNlbnNpYmxlCnMxX2xiX2luaXRfcG9wX3NpemUgPC0gc3VtKHMxX2xiX3BvcCkKYGBgCgpgYGB7cn0KczFfbGJfbGFuZHNjYXBlIDwtIGxhbmRzY2FwZShwb3B1bGF0aW9uID0gczFfbGJfcG9wLAogICAgICAgICAgICAgICAgICAgICAgICAgIHN1aXRhYmlsaXR5ID0gczFfaHNfbGIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FycnlpbmdfY2FwYWNpdHkgPSBzMV9oYWJfa19sYikKCnMxX2xiX3BvcF9keW5hbWljcyA8LSBwb3B1bGF0aW9uX2R5bmFtaWNzKGNoYW5nZSA9IGdyb3d0aCh0cmFuc2l0aW9uX21hdHJpeCA9IGxiX3RyYW5zX21hdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbF9zdG9jaGFzdGljaXR5ID0gMC4zKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGVyc2FsID0gZmFzdF9kaXNwZXJzYWwoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGVyc2FsX2tlcm5lbCA9IGV4cG9uZW50aWFsX2Rpc3BlcnNhbF9rZXJuZWwoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0YW5jZV9kZWNheSA9IDIwMDApKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZpY2F0aW9uID0gTlVMTCkKYGBgCgpgYGB7cn0KcGxhbihzZXF1ZW50aWFsLCB3b3JrZXJzID0gMSkKczFfbGJfcmVzdWx0c18xXzUwIDwtIHNpbXVsYXRpb24obGFuZHNjYXBlID0gczFfbGJfbGFuZHNjYXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgcG9wdWxhdGlvbl9keW5hbWljcyA9IHMxX2xiX3BvcF9keW5hbWljcywKICAgICAgICAgICAgICAgICAgICAgICAgIGhhYml0YXRfZHluYW1pY3MgPSBOVUxMLAogICAgICAgICAgICAgICAgICAgICAgICAgdGltZXN0ZXBzID0gNTAsCiAgICAgICAgICAgICAgICAgICAgICAgICByZXBsaWNhdGVzID0gMSkKCgpzYXZlUkRTKG9iamVjdCA9IHMxX2xiX3Jlc3VsdHNfMV81MCwgZmlsZSA9ICJvdXRwdXQvcHZhX3Jlc3VsdHMvczFfbGJfcmVzdWx0c18xXzUwLlJkcyIpCmBgYAoKCmBgYHtyfQpwbG90KHMxX2xiX3Jlc3VsdHNfMV81MCkKYGBgCgpgYGB7cn0KcGxvdChzMV9sYl9yZXN1bHRzXzFfNTBbMV0sIHR5cGUgPSAicmFzdGVyIiwgc3RhZ2VzID0gMCwgdGltZXN0ZXBzID0gYygxOjUpKQpgYGAKCiMjIyBTY2VuYXJpbyAzCmBgYHtyfQpzM19oc19sYiA8LSBzdGFjayhzM19pcF9sYiwgczNfZnBfbGIpCgpmb3IoaSBpbiAxOjUxKXsKICBzM19oc19sYltbaV1dW2lzLm5hKHMzX2hzX2xiW1tpXV1bXSldIDwtIDAKfQoKczNfaHNfbGIgPC0gbWFzayhzM19oc19sYiwgbWFzayA9IGNoX21hc2spCmBgYAoKYGBge3J9CnMzX2hhYl9rX2xiIDwtIGNhbGMoczNfaHNfbGJbWzFdXSwgZnVuID0gZnVuY3Rpb24oeCl7aWYoaXMubmEoeCkpIHggZWxzZSByYmlub20ocHJvYiA9IHgsIHNpemUgPSAzLCBuID0gMSl9KQoKbmFtZXMoczNfaGFiX2tfbGIpIDwtICJjYXJyeWluZ0NhcGFjaXR5IgoKczNfbGJfcG9wTiA8LSBzdGFjayhyZXBsaWNhdGUobmNvbChsYl90cmFuc19tYXQpLCBzM19oYWJfa19sYikpCgpzM19sYl9wb3BOIDwtIHMzX2xiX3BvcE4qbGJfc3RhYmxlX3N0YXRlcwoKczNfbGJfaWR4IDwtIHdoaWNoKCFpcy5uYShzM19oc19sYltbMV1dW10pICYgczNfaHNfbGJbWzFdXVtdIDwgMC45NSkKCnMzX2xiX3BvcCA8LSBzM19sYl9wb3BOCnMzX2xiX3BvcFshaXMubmEoczNfbGJfcG9wKV0gPC0gMApzM19sYl9wb3BbWzFdXVtzYW1wbGUoczNfbGJfaWR4LCAzMDAwKV0gPC0gMQpzM19sYl9wb3BbWzJdXVtzYW1wbGUoczNfbGJfaWR4LCAzMDAwKV0gPC0gMQpzM19sYl9wb3BbWzNdXVtzYW1wbGUoczNfbGJfaWR4LCAzMDAwKV0gPC0gMQoKczNfbGJfcG9wIDwtIHMzX2xiX3BvcCpjaF9tYXNrCgpuYW1lcyhzM19sYl9wb3ApIDwtIGNvbG5hbWVzKGxiX3RyYW5zX21hdCkKCnMzX2xiX1RvdHBvcE4gPC0gc3VtKGNlbGxTdGF0cyhzM19sYl9wb3AsICdzdW0nLCBuYS5ybSA9IFRSVUUpKSAjIEdldCB0b3RhbCBwb3B1bGF0aW9uIHNpemUgdG8gY2hlY2sgc2Vuc2libGUKczNfbGJfaW5pdF9wb3Bfc2l6ZSA8LSBzdW0oczNfbGJfcG9wKQpgYGAKCmBgYHtyfQpzM19sYl9sYW5kc2NhcGUgPC0gbGFuZHNjYXBlKHBvcHVsYXRpb24gPSBzM19sYl9wb3AsCiAgICAgICAgICAgICAgICAgICAgICAgICAgc3VpdGFiaWxpdHkgPSBzM19oc19sYiwKICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJyeWluZ19jYXBhY2l0eSA9IHMzX2hhYl9rX2xiKQoKczNfbGJfcG9wX2R5bmFtaWNzIDwtIHBvcHVsYXRpb25fZHluYW1pY3MoY2hhbmdlID0gZ3Jvd3RoKHRyYW5zaXRpb25fbWF0cml4ID0gbGJfdHJhbnNfbWF0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2xvYmFsX3N0b2NoYXN0aWNpdHkgPSAwLjEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNwZXJzYWwgPSBmYXN0X2Rpc3BlcnNhbCgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNwZXJzYWxfa2VybmVsID0gZXhwb25lbnRpYWxfZGlzcGVyc2FsX2tlcm5lbCgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RhbmNlX2RlY2F5ID0gODAwMCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RpZmljYXRpb24gPSBOVUxMKQpgYGAKCmBgYHtyfQpwbGFuKHNlcXVlbnRpYWwsIHdvcmtlcnMgPSAxKQpzM19sYl9yZXN1bHRzXzFfNTAgPC0gc2ltdWxhdGlvbihsYW5kc2NhcGUgPSBzM19sYl9sYW5kc2NhcGUsCiAgICAgICAgICAgICAgICAgICAgICAgICBwb3B1bGF0aW9uX2R5bmFtaWNzID0gczNfbGJfcG9wX2R5bmFtaWNzLAogICAgICAgICAgICAgICAgICAgICAgICAgaGFiaXRhdF9keW5hbWljcyA9IE5VTEwsCiAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lc3RlcHMgPSA1MCwKICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxpY2F0ZXMgPSAxKQoKCnNhdmVSRFMob2JqZWN0ID0gczNfbGJfcmVzdWx0c18xXzUwLCBmaWxlID0gIm91dHB1dC9wdmFfcmVzdWx0cy9zM19sYl9yZXN1bHRzXzFfNTAuUmRzIikKYGBgCgpgYGB7cn0KcGxvdChzM19sYl9yZXN1bHRzXzFfNTApCmBgYAoKYGBge3J9CnBsb3QoczNfbGJfcmVzdWx0c18xXzUwWzFdLCB0eXBlID0gInJhc3RlciIsIHN0YWdlcyA9IDAsIHRpbWVzdGVwcyA9IGMoMTo1KSkKYGBgCgojIyMgU2NlbmFyaW8gNApgYGB7cn0KczRfaHNfbGIgPC0gc3RhY2soczRfaXBfbGIsIHM0X2ZwX2xiKQoKZm9yKGkgaW4gMTo1MSl7CiAgczRfaHNfbGJbW2ldXVtpcy5uYShzNF9oc19sYltbaV1dW10pXSA8LSAwCn0KCnM0X2hzX2xiIDwtIG1hc2soczRfaHNfbGIsIG1hc2sgPSBjaF9tYXNrKQpgYGAKCmBgYHtyfQpzNF9oYWJfa19sYiA8LSBjYWxjKHM0X2hzX2xiW1sxXV0sIGZ1biA9IGZ1bmN0aW9uKHgpe2lmKGlzLm5hKHgpKSB4IGVsc2UgcmJpbm9tKHByb2IgPSB4LCBzaXplID0gMywgbiA9IDEpfSkKCm5hbWVzKHM0X2hhYl9rX2xiKSA8LSAiY2FycnlpbmdDYXBhY2l0eSIKCnM0X2xiX3BvcE4gPC0gc3RhY2socmVwbGljYXRlKG5jb2wobGJfdHJhbnNfbWF0KSwgczRfaGFiX2tfbGIpKQoKczRfbGJfcG9wTiA8LSBzNF9sYl9wb3BOKmxiX3N0YWJsZV9zdGF0ZXMKCnM0X2xiX2lkeCA8LSB3aGljaCghaXMubmEoczRfaHNfbGJbWzFdXVtdKSAmIHM0X2hzX2xiW1sxXV1bXSA8IDAuOTUpCgpzNF9sYl9wb3AgPC0gczRfbGJfcG9wTgpzNF9sYl9wb3BbIWlzLm5hKHM0X2xiX3BvcCldIDwtIDAKczRfbGJfcG9wW1sxXV1bc2FtcGxlKHM0X2xiX2lkeCwgMzAwMCldIDwtIDEKczRfbGJfcG9wW1syXV1bc2FtcGxlKHM0X2xiX2lkeCwgMzAwMCldIDwtIDEKczRfbGJfcG9wW1szXV1bc2FtcGxlKHM0X2xiX2lkeCwgMzAwMCldIDwtIDEKCnM0X2xiX3BvcCA8LSBzNF9sYl9wb3AqY2hfbWFzawoKbmFtZXMoczRfbGJfcG9wKSA8LSBjb2xuYW1lcyhsYl90cmFuc19tYXQpCgpzNF9sYl9Ub3Rwb3BOIDwtIHN1bShjZWxsU3RhdHMoczRfbGJfcG9wLCAnc3VtJywgbmEucm0gPSBUUlVFKSkgIyBHZXQgdG90YWwgcG9wdWxhdGlvbiBzaXplIHRvIGNoZWNrIHNlbnNpYmxlCnM0X2xiX2luaXRfcG9wX3NpemUgPC0gc3VtKHM0X2xiX3BvcCkKYGBgCgpgYGB7cn0KczRfbGJfbGFuZHNjYXBlIDwtIGxhbmRzY2FwZShwb3B1bGF0aW9uID0gczRfbGJfcG9wLAogICAgICAgICAgICAgICAgICAgICAgICAgIHN1aXRhYmlsaXR5ID0gczRfaHNfbGIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FycnlpbmdfY2FwYWNpdHkgPSBzNF9oYWJfa19sYikKCnM0X2xiX3BvcF9keW5hbWljcyA8LSBwb3B1bGF0aW9uX2R5bmFtaWNzKGNoYW5nZSA9IGdyb3d0aCh0cmFuc2l0aW9uX21hdHJpeCA9IGxiX3RyYW5zX21hdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbF9zdG9jaGFzdGljaXR5ID0gMC4xKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGVyc2FsID0gZmFzdF9kaXNwZXJzYWwoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGVyc2FsX2tlcm5lbCA9IGV4cG9uZW50aWFsX2Rpc3BlcnNhbF9rZXJuZWwoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0YW5jZV9kZWNheSA9IDgwMDApKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZpY2F0aW9uID0gTlVMTCkKYGBgCgpgYGB7cn0KcGxhbihzZXF1ZW50aWFsLCB3b3JrZXJzID0gMSkKczRfbGJfcmVzdWx0c18xXzUwIDwtIHNpbXVsYXRpb24obGFuZHNjYXBlID0gczRfbGJfbGFuZHNjYXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgcG9wdWxhdGlvbl9keW5hbWljcyA9IHM0X2xiX3BvcF9keW5hbWljcywKICAgICAgICAgICAgICAgICAgICAgICAgIGhhYml0YXRfZHluYW1pY3MgPSBOVUxMLAogICAgICAgICAgICAgICAgICAgICAgICAgdGltZXN0ZXBzID0gNTAsCiAgICAgICAgICAgICAgICAgICAgICAgICByZXBsaWNhdGVzID0gMSkKCgpzYXZlUkRTKG9iamVjdCA9IHM0X2xiX3Jlc3VsdHNfMV81MCwgZmlsZSA9ICJvdXRwdXQvcHZhX3Jlc3VsdHMvczRfbGJfcmVzdWx0c18xXzUwLlJkcyIpCmBgYAoKCmBgYHtyfQpwbG90KHM0X2xiX3Jlc3VsdHNfMV81MCkKYGBgCgpgYGB7cn0KcGxvdChzNF9sYl9yZXN1bHRzXzFfNTBbMV0sIHR5cGUgPSAicmFzdGVyIiwgc3RhZ2VzID0gMCwgdGltZXN0ZXBzID0gYygxOjUpKQpgYGAKCgo=